【问题标题】:Without media queries how to achieve 3 column desktop to 1 column mobile layout无媒体查询如何实现3列桌面转1列移动布局
【发布时间】:2021-04-23 04:40:32
【问题描述】:

在这里查看了一些问题,但它们并没有完全解决我正在寻找的问题。

假设我有一个网站并且我想要。在桌面上我想要这个:

这很容易。 grid-template-columns: repeat(3, 33%)(基本上)

但是,在移动设备上,我想要这个

我遇到的是在它翻转到单列之前发生的:

我正在尝试clamp()minmax() 和各种各样的东西,但没有任何东西能按我的意愿工作。是的,我完全可以使用媒体查询,但我希望使用现代 CSS(如钳位、网格、最小最大值等)创建真正流畅的网格/柔性布局,这样就不需要媒体查询来进行基本的布局更改。

我知道这不起作用,但作为一个起点,这里是我 100 次尝试之一的简单版本:) 在这个版本中,我试图使用钳位从重复 (3) 切换到重复 (1 )。

.wrapper {
  display: grid;
  gap: 15px;
  grid-template-columns: repeat(clamp(1, calc(100% - 500px), 3), 33%);
}

.one {
  background: red;
}

.two {
  background: green;
}

.three {
  background: blue;
}
<div class="wrapper">
  <div class="item one"><h3>Example A</h3></div>
  <div class="item two"><h3>Example Two</h3></div>
  <div class="item three"><h3>Third Example</h3></div>
</div>

【问题讨论】:

  • 你能分享你的代码吗?
  • 我省略了,因为我试图获得更高级的概念,但我现在确实在上面包含了一个简单的例子。
  • 您有机会查看我的答案吗?

标签: css flexbox css-grid


【解决方案1】:

您可以通过使用这样的网格来实现这一点:

.btnContainer {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)); /* here you set when the width should change to be moved to the next row, in this example, the divs will move when the screen reduces size and their width is less than 200px */
}

.btnCenter3 {
  background-color: rgb(6, 198, 247);
  height: 400px;
}
.btnCenter4 {
  height: 400px;
  background-color: rgb(196, 95, 1);
}
.btnCenter5 {
  height: 400px;
  background-color: rgb(192, 231, 19);
}
<div class="btnContainer">
<div class="btnCenter3"></div>
      <div class="btnCenter4"></div>
      <div class="btnCenter5"></div>
 </div>

【讨论】:

  • 不理解反对票。如果您检查代码 sn-p,它会按照您的要求执行。在桌面模式下,它将显示三列,而在移动屏幕上,它将显示一列。没有使用媒体查询!
  • 我没有投反对票,但这遇到了我描述的相同问题。它在第 1 行变成蓝棕色,然后在第 2 行变成绿色。
【解决方案2】:

这是一个在 flex-basis 中使用 max(0px, (400px - 100vw)*1000) 的想法。如果100vw(屏幕尺寸)大于400px,则此公式将给出0px,或者在相反的情况下给每个元素一个很大的flex-basis 并创建一个包装。只需调整起@media (max-width:400px)作用的400px即可

.container {
  display:flex;
  flex-wrap:wrap;
}

.container div {
  height:100px;
  border:2px solid;
  background:red;
  flex-basis:max(0px, (400px - 100vw)*1000);
  flex-grow:1;
}
<div class="container">
  <div></div>
  <div></div>
  <div></div>
</div>

使用 CSS 网格可以如下所示:

.container {
  display:grid;
  grid-template-columns:repeat(auto-fill,minmax(clamp(30%, (400px - 100vw)*1000, 100%),1fr));
  grid-gap:5px;
}

.container div {
  height:100px;
  border:2px solid;
  background:red;
}
<div class="container">
  <div></div>
  <div></div>
  <div></div>
</div>

一个类似的问题,我在没有媒体查询的情况下控制最大列数:CSS grid maximum number of columns without media queries


我们可以扩展上述解决方案以考虑更复杂的情况。

从 6 列移动到 3 列再到 1 列的示例:

.container {
  display:grid;
  grid-template-columns:
    repeat(auto-fill,
      minmax(clamp(clamp(15%,(800px - 100vw)*1000, 30%), (400px - 100vw)*1000, 100%)
      /* if(screen> 800px) 15% elseif(screen> 400px) 30% else 100% */
      ,1fr));
  grid-gap:5px;
}

.container div {
  height:100px;
  border:2px solid;
  background:red;
}
<div class="container">
  <div></div>
  <div></div>
  <div></div>
  <div></div>
  <div></div>
  <div></div>
</div>

要了解这些值,请考虑以下范围:

100%/7  100%/6  100%/5  100%/4  100%/3  100%/2  100%/1
 14.3%  16.7%    20%     25%     33.3%   50%     100%

要获得 6 列,我们需要一个在 ]14.3% 16.7%] 范围内的值(我考虑过 15%) 要获得 3 列,我们需要在]25% 33.3%] 范围内的值(我考虑过30%

我们只是避免边缘以确保我们考虑到差距。

使用 CSS 变量的更通用的解决方案,我将在其中添加 0.1% 以确保该值足够大以获得所需的列数并且可以保持间隙。

我们还要添加一些动态着色(相关:How to change the color of <div> Element depending on its height or width?

.container {
  /* first breakpoint*/
  --w1:800px;
  --n1:6;
  /* second breakpoint*/
  --w2:400px;
  --n2:3;

  display:grid;
  grid-template-columns:
    repeat(auto-fill,
      minmax(clamp(clamp(100%/(var(--n1) + 1) + 0.1%, (var(--w1) - 100vw)*1000,
                         100%/(var(--n2) + 1) + 0.1%), (var(--w2) - 100vw)*1000,
                         100%), 1fr));
  grid-gap:5px;
  margin:10px 0;
}

.container div {
  height:100px;
  border:2px solid;
  background:
    linear-gradient(blue  0 0) 0 /1% calc(var(--w2) - 100vw),
    linear-gradient(green 0 0) 0 /1% calc(var(--w1) - 100vw),
    red;
}
<div class="container">
  <div></div>
  <div></div>
  <div></div>
  <div></div>
  <div></div>
  <div></div>
</div>

<div class="container" style="--w1:900px;--n1:8;--w2:500px;--n2:4;grid-gap:10px;">
  <div></div>
  <div></div>
  <div></div>
  <div></div>
  <div></div>
  <div></div>
  <div></div>
  <div></div>
</div>

<div class="container" style="--w1:600px;--n1:4;--n2:2;grid-gap:2vw;">
  <div></div>
  <div></div>
  <div></div>
  <div></div>
  <div></div>
  <div></div>
</div>

使用 flexbox,我们可以有不同的(可能是想要的)行为,其中一行的最后一项将占用所有可用空间:

.container {
  /* first breakpoint*/
  --w1:800px;
  --n1:6;
  /* second breakpoint*/
  --w2:400px;
  --n2:3;

  display:flex;
  flex-wrap:wrap;
  margin:10px 0;
}

.container div {
  height:100px;
  border:2px solid;
  margin:5px;
  flex-basis:clamp(clamp(100%/(var(--n1) + 1) + 0.1% ,(var(--w1) - 100vw)*1000, 
                         100%/(var(--n2) + 1) + 0.1%),(var(--w2) - 100vw)*1000, 
                         100%);
  flex-grow:1;
  box-sizing:border-box;
  background:
    linear-gradient(blue  0 0) 0 /1% calc(var(--w2) - 100vw),
    linear-gradient(green 0 0) 0 /1% calc(var(--w1) - 100vw),
    red;
}
<div class="container">
  <div></div>
  <div></div>
  <div></div>
  <div></div>
  <div></div>
  <div></div>
</div>

<div class="container" style="--w1:900px;--n1:8;--w2:500px;--n2:4;">
  <div></div>
  <div></div>
  <div></div>
  <div></div>
  <div></div>
  <div></div>
  <div></div>
  <div></div>
</div>

<div class="container" style="--w1:600px;--n1:4;--n2:2;">
  <div></div>
  <div></div>
  <div></div>
  <div></div>
  <div></div>
  <div></div>
</div>

【讨论】:

    【解决方案3】:

    @Temani 的回答很疯狂,但很棒:)。我需要为 4 列布局实现类似的东西(分解为 2 列然后 1 列),但发现替换 25 和 50 的 15 和 30 百分比值不起作用。这似乎与百分比需要考虑网格间隙的事实有关,因此@Temani 的答案仅由于舍入“错误”而真正有效。因此,基于 4 col 网格的更强大(甚至更疯狂)的解决方案是:

    :root {
      --grid-gap: 10px;
      --grid-gap-x2: calc(var(--grid-gap));
    }
    
    .container {
      display:grid;
      grid-gap: var(--grid-gap-x2);
      grid-template-columns:
        repeat(auto-fill, minmax(clamp(clamp(calc(25% - var(--grid-gap-x2)),(800px - 100vw)*1000, calc(50% - var(--grid-gap-x2))), (400px - 100vw)*1000, 100%)
          /* if(screen> 800px) 25% elseif(screen> 400px) 50% else 100%. */
          /* (Subtracting grid gap from either side of percentage width.) */
          ,1fr));
    }
    

    【讨论】:

    • answer 仅因为舍入“错误”而真正有效 --> 这不是错误,我依赖 1fr 功能,所以我不需要考虑这个差距,我只需要使它足够大以获得所需的列数。 30% 大于 25% 且小于 33%,因此使用 1fr 我将获得 3 列。 15% 的逻辑相同
    猜你喜欢
    • 2016-01-05
    • 1970-01-01
    • 1970-01-01
    • 2019-10-30
    • 2012-10-13
    • 2021-12-24
    • 2019-05-07
    • 2018-11-22
    相关资源
    最近更新 更多