没有媒体查询如何实现3列桌面到1列移动布局 [英] Without media queries how to achieve 3 column desktop to 1 column mobile layout
问题描述
在这里研究了一些问题,但它们并没有完全解决我正在寻找的问题.
假设我有一个网站并且我想要.在桌面上我想要这个:
这很容易.grid-template-columns: repeat(3, 33%)
(基本上)
然而,在移动设备上,我想要这个
我遇到的是在它翻转到单列之前发生的:
我正在尝试 clamp()
、minmax()
和各种各样的东西,但没有任何东西能如我所愿.是的,我完全可以使用媒体查询,但我希望使用现代 CSS(如夹子、网格、最小最大值等)创建真正流畅的网格/弹性布局,这样基本布局更改就不需要媒体查询.
我知道这行不通,但作为起点,这里是我 100 次尝试之一的简单版本:) 在这个版本中,我试图使用clamp 从repeat(3) 切换到repeat(1)).
.wrapper {显示:网格;间隙:15px;网格模板列:repeat(clamp(1, calc(100% - 500px), 3), 33%);}.一 {背景:红色;}.二 {背景:绿色;}.三 {背景:蓝色;}
<div class="item one"><h3>示例A</h3></div><div class="item二"><h3>示例二</h3></div><div class="item三"><h3>第三个例子</h3></div>
这是一个在 flex-basis 中使用 max(0px, (400px - 100vw)*1000)
的想法.如果 100vw
(屏幕尺寸)大于 400px
或在相反的情况下给每个元素一个非常大的值,则此公式将给 0px
大 flex-basis
并创建一个包装.只需调整400px
,起到@media(max-width:400px)
.container {显示:弹性;弹性包裹:包裹;}.container div {高度:100px;边框:2px 实心;背景:红色;flex-basis:max(0px, (400px - 100vw)*1000);弹性增长:1;}
<div></div><div></div><div></div>
使用 CSS 网格可以如下所示:
.container {显示:网格;网格模板列:重复(自动填充,minmax(clamp(30%,(400px - 100vw)* 1000,100%),1fr));网格间隙:5px;}.container div {高度:100px;边框:2px 实心;背景:红色;}
<div></div><div></div><div></div>
一个类似的问题,我在没有媒体查询的情况下控制最大列数:没有媒体查询的 CSS 网格最大列数一个>
我们可以扩展上述解决方案以考虑更复杂的情况.
从 6 到 3 再到 1 列的示例:
.container {显示:网格;网格模板列:重复(自动填充,minmax(clamp(clamp(15%,(800px - 100vw)*1000, 30%), (400px - 100vw)*1000, 100%)/* if(screen> 800px) 15% elseif(screen> 400px) 30% else 100% */,1fr));网格间隙:5px;}.container div {高度:100px;边框:2px 实心;背景:红色;}
<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%/114.3% 16.7% 20% 25% 33.3% 50% 100%
要获得 6 列,我们需要 ]14.3% 16.7%]
范围内的值(我考虑了 15%
)要获得 3 列,我们需要一个 ]25% 33.3%]
范围内的值(我考虑过 30%
)
我们只是避开边缘以确保我们考虑到间隙.
使用 CSS 变量的更通用的解决方案,我将添加 0.1%
以确保该值足够大以获得所需的列数并且可以保持差距.
我们还要添加一些动态着色(相关:如何根据
.container {/* 第一个断点*/--w1:800px;--n1:6;/* 第二个断点*/--w2:400px;--n2:3;显示:网格;网格模板列:重复(自动填充,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));网格间隙:5px;边距:10px 0;}.container div {高度:100px;边框:2px 实心;背景:线性梯度(蓝色 0 0) 0/1% calc(var(--w2) - 100vw),线性梯度(绿色 0 0) 0/1% calc(var(--w1) - 100vw),红色的;}
<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 class="container" style="--w1:600px;--n1:4;--n2:2;grid-gap:2vw;"><div></div><div></div><div></div><div></div><div></div><div></div>
使用 flexbox 我们可以有不同的(可能是想要的)行为,其中一行的最后一项将占用所有可用空间:
.container {/* 第一个断点*/--w1:800px;--n1:6;/* 第二个断点*/--w2:400px;--n2:3;显示:弹性;弹性包裹:包裹;边距:10px 0;}.container div {高度:100px;边框:2px 实心;边距: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%);弹性增长:1;box-sizing:border-box;背景:线性梯度(蓝色 0 0) 0/1% calc(var(--w2) - 100vw),线性梯度(绿色 0 0) 0/1% calc(var(--w1) - 100vw),红色的;}
<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 class="container" style="--w1:600px;--n1:4;--n2:2;"><div></div><div></div><div></div><div></div><div></div><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:
This is easy. grid-template-columns: repeat(3, 33%)
(basically)
On mobile, however, I want this
What I'm running into is happens before it flips to a single column:
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>
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>
这篇关于没有媒体查询如何实现3列桌面到1列移动布局的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!