没有媒体查询如何实现3列桌面到1列移动布局

发布于 2025-02-11 01:09:33 字数 1571 浏览 2 评论 0原文

在这里研究了一些问题,但他们并没有完全解决我想要的东西。

说我有一个网站,我想要。在桌面上我想要:

”在此处输入图像描述”

这很容易。 网格 - 板块 - 列:重复(3,33%)(基本上)

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

“在这里输入图像描述”

我遇到的事情发生在它翻转之前发生到一个列:

“在此处输入图像描述”

我正在尝试clamp()minmax(),以及各种各样的东西想。是的,我可以完全使用媒体查询,但是我希望使用夹具,网格,Minmax等现代CS创建真正的流体网格/Flex布局,因此不需要对基本布局更改进行媒体查询。

我知道这不起作用,但是作为要求的起点,这是我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>

Looked into a few questions here but they don't quite solve what I'm looking for.

Say I have a website and I want. On desktop I want this:

enter image description here

This is easy. grid-template-columns: repeat(3, 33%) (basically)

On mobile, however, I want this

enter image description here

What I'm running into is happens before it flips to a single column:

enter image description here

I'm trying clamp(), minmax(), and all sorts of things but nothing ever works as I want. Yes, I can totally use a media query but I was hoping to create a truly fluid grid/flex layout using modern CSS like clamp, grid, minmax, etc so there wouldn't be a need for media queries for basic layout changes.

I know this doesn't work but as a starting point as requested here's a simple version of one of my 100 attempts :) In this version I was trying to use clamp to switch from a repeat(3) to repeat(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>

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

凡间太子 2025-02-18 01:09:33

我写了一篇详细的文章,其中包含更多通用规则: https:https://// css-tricks.com/responsive-layouts-fewer-media-ceries/

以下是一个想法,使用max(0px,(400px-100vw)*1000 -基础。如果100VW(屏幕大小)大于400px或相反的情况,则此公式将给出0px(屏幕大小)(屏幕大小)大于400px Big flex-basis并创建一个包装。只需调整400px扮演@Media(最大宽度: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-无媒体查询的最大列数


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

从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%,以确保该值足够大以获得所需的列数,并且可以保持差距。

我们还添加一些动态的颜色(相关:如何根据其高度或宽度更改&lt; div; div; div; div; >)

.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>

I wrote a detailed article with more generic rules: https://css-tricks.com/responsive-layouts-fewer-media-queries/

Here is an idea using max(0px, (400px - 100vw)*1000) inside flex-basis. This formula will eiter give 0px if 100vw (screen size) is bigger than 400px or a very big value in the opposite case giving each element a big flex-basis and create a wrapping. Simply adjust the 400px which play the role of @media (max-width: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>

Using CSS grid it can be like below:

.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>

A similar question where I am controling the maximum number of columns without media query: CSS grid - maximum number of columns without media queries


We can scale the above solution to consider more complex cases.

Example of moving from 6 to 3 to 1 column:

.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>

To understand the values consider the following ranges:

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

To get 6 columns we need a value in the range ]14.3% 16.7%] (I considered 15%)
To get 3 columns we need a value in the range ]25% 33.3%] (I considered 30%)

We simply avoid the edges to make sure we account for the gaps.

A more generic solution using CSS variables where I will add 0.1% to make sure the value is big enough to get the needed number of column and it can hold the gap.

Let's also add some dynamic coloration (related: 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>

Using flexbox where we can have a different (probably wanted) behavior where the last item of a row will take all the free space:

.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>

╰つ倒转 2025-02-18 01:09:33

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

.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>

You can achive this by using grid like this:

.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>

无声无音无过去 2025-02-18 01:09:33

@Temani的答案是傻瓜,但很棒:)。我需要为4列布局实施类似的东西(分解2个Cols然后是1个Col),但发现替换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));
}

@Temani's answer is bonkers but great :). I needed to implement a similar thing for a 4 column layout (breaking to 2 cols then 1 col) but found that replacing the 15 and 30 percentage values for 25 and 50 didn't work. This seems to be related to the fact that the percentages need to take account of the grid gap, so @Temani's answer only really works because of the rounding 'error'. So a more robust (if even more bonkers) solution, based on a 4 col grid is:

: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));
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文