flex 布局 自适应 靠左对齐

需求

假设我有5个300px*300px的卡片,须要根据屏幕宽度自适用平铺排列,并在换行的时候靠左对齐。css

不能用js实现,用js就太简单了,并且代码会比较啰嗦和让人困扰。 html

需求

核心知识

  • 利用flex容器的justify-content: flex-startflex-wrap: wrap完成自动换行靠左需求
  • 利用calc和margin-left完成子项目平铺需求

单单利用justify-content: space-evenly完成不了需求

直觉上,利用这个属性和wrap就能够知足,但实际上不能够,由于会每行各自计算空隙,这样会致使最后一行对不齐,效果以下浏览器

space-evenly

利用flex-startmargin-left: calc实现

1. 数学公式

flex-start能够知足咱们靠左对齐的需求。接下来,咱们只要完成间距的需求就能够了。子项目宽度是固定的300px,那么根据容器的宽度,确定就能计算出来间距了,例如宽1000px的容器,那确定只能容纳3个子项目,剩余100px空间,一个四个空隙,那每一个空隙就是25px。bash

  • conWidth 容器宽度
  • itemWidth 子项目宽度
  • 每行子项目个数 n = Math.floor(conWidth/itemWidth)
marginLeft
= \frac {conWidth - n \times itemWidth}{n + 1}
= \frac {conWidth - Math.floor(conWidth/itemWidth) \times itemWidth}{Math.floor(conWidth/itemWidth) + 1}

嗯,貌似是搞定了,咱们转化成css中calc就是:布局

margin-left: calc((100% - Math.floor(100% / 300px) * 300px) / Math.floor(100% / 300px))
复制代码

可是,calc根本不支持这样:flex

  • calc没有Math.floor方法
  • calc中除法后面必须是数字

2. 利用@media 媒体查询解决每行个数问题

既然没法经过calc直接计算出来n,那就想办法跳过这一步。这样咱们只须要完成左边的公式就好了。spa

嗯,由于咱们子项目是定宽的300px,那么:容器少于900px,就只能放2个,少于1200px,就只能放3个。。。。 多写几个相似下面的媒体查询就能够了3d

@media screen and (max-width: 1200px) and (min-width: 900px) {
  item { --n: 3; }
}
复制代码

而后咱们的margin-left就能够简化成以下calc支持的左边的公式了code

margin-left: calc((100% - var(--itemWidth) * var(--n)) / (var(--n) + 1));
复制代码

3. 最终代码

htmlcdn

<div class="container">
    <item>1</item>
    <item>2</item>
    <item>3</item>
    <item>4</item>
    <item>5</item>
/div>
复制代码

css

.container {
  background: gold;
  display: flex;
  justify-content: flex-start;
  flex-wrap: wrap;
}

item {
  outline: 1px solid black;
  height: 300px;
  background: red;
  margin-top: 20px;
  --itemWidth: 300px; /* 和项目宽度一致 */
  width: calc(var(--itemWidth));
  margin-left: calc((100% - var(--itemWidth) * var(--n)) / (var(--n) + 1));
}
  
@media screen and (max-width: 900px) {
  item { --n: 2; }
}

@media screen and (max-width: 1200px) and (min-width: 900px) {
  item { --n: 3; }
}

@media screen and (max-width: 1500px) and (min-width: 1200px) {
  item { --n: 4; }
}

@media screen and (max-width: 8888px) and (min-width: 1500px) {
  item { --n: 5; } /* 最多一行显示五个 */
}

复制代码

经过缩放浏览器观察,已经实现自适用屏幕宽度了。

自适用

1. float布局也能够这样解决

思路同样,可是flex的其余特性就使用不了了

2. 若是没法使用css中的var,例如ie浏览器

那就只要把margin-left总体写到@media 媒体查询里便可

3. 使用grid布局更简单

若是使用grid布局,calc都不须要用到了,只要在@media中写好grid样式,在不一样宽度下有不一样列数便可 请看个人另一篇文章

4. 能够简化公式

直接每一个项目宽度 100% / n 便可,可是那样html代码就会很啰嗦,每一个子项目都须要再套一层,做为真正的flex项目使用。

相关文章
相关标签/搜索