欢迎来到DIVCSS5查找CSS资料与学习DIV CSS布局技术!
经过了基础篇和使用篇后,相信你已经一定程度上了解了 CSS 自定义属性.现在就让我们来看看如何运用它提高代码的复用率、协助开发者将代码模块化吧.
 
模块化 CSS:可配置的网格布局
 
虽然现在我们有了 CSS Grid,你还是可以用 flexbox 去实现网格布局.尽可能地将你的实现抽象成一个可复用可定制的模块,这将会是一个有趣的练习.来,先看看最直白的做法吧:
 
.grid {  
 
  display: flex;
 
  flex-direction: row;
 
  flex-wrap: wrap;
 
  padding: calc(var(--margin) / 2);
 
}
 
.grid > .cell {
 
  display: block;
 
  width: calc(100% / var(--columns) - var(--margin));
 
  margin: calc(var(--margin) / 2);
 
}
 
要如何模块化上面的代码?首先,作为一个模块需要沙盒机制,所以先给它们都加上命名空间,取名有很多种方式,比如 BEM 还有 SMACSS.不过简洁起见.在本文里我们暂时用 my- 作为前缀.再补充上变量定义和一些注释:
 
.my-grid {
 
  /* CSS 变量定义
 
     网格的列数 网格边距 列与列的间距 */
 
  --my-grid-columns: 1;
 
  --my-grid-margin: 16px;
 
  display: flex;
 
  flex-direction: row;
 
  flex-wrap: wrap;
 
  /* 兼容代码 */
 
  padding: 8px;
 
  padding: calc(var(--my-grid-margin) / 2);
 
}
 
看起来 my-grid 已经被封装成一个像模像样的模块了,那么要如何使用它呢?
 
<link rel="stylesheet" href="my-grid.css">
 
引入样式表之后,根据样式覆盖原则,在默认样式的之后对 CSS 变量赋上新值:
 
<link rel="stylesheet" href="my-grid.css">
 
<style>
 
  .my-grid {
 
    --my-grid-columns: 2;
 
  }
 
</style> 
 
当然,你也可以在其他的选择器中对变量赋值;还能通过媒体查询,在不同的场景下使用不同的值:
 
.my-app .my-grid {
 
  --my-grid-columns: 1;
 
  --my-grid-margin: 8px;
 
}
 
@media (min-size: 600px) {
 
  .my-app .my-grid {
 
    --my-grid-columns: 3;
 
    --my-grid-margin: 16px;
 
  }
 
}
 
@media (min-size: 1024px) {
 
  .my-app .my-grid {
 
    --my-grid-columns: 6;
 
    --my-grid-margin: 16px;
 
  }
 
}
 
请注意,以上所有的配置统统是纯 CSS 实现的,不需要切换不同的类名改变网格的布局.这说明,模块开发者不需要提供一系列 CSS 类名给模块使用者了.只要提供了 CSS 变量,模块使用者就能灵活地去设置它们,也不再受限于开发者提供的类名.
 
应用场景之二:图片长宽比
 
假如你正在搭建自己的博客,你想给图片元素设置 max-width,防止它超出容器的范围:
 
.my-content {
 
  max-width: 600px;
 
}
 
如果一开始图片没有占位,那么在图片加载的时候页面内容会不断往下移动,所以一开始就要为图片占好位.在 img 标签中直接定义了宽高的话:
 
<img src="kitten.jpg" height="1024" width="768" alt="A cute kitten">
 
图片在自适应窗口宽度的时候,浏览器是不会保证它的横纵比的,它只能保证图片的高度是 768px 同时让图片的宽度不要超过 600px(CSS 中的定义),结果我们会得到一张变形的图片( 图片版权所属 latch.r ):
 
那么你要怎么保证图片在任何场景下都不变形?使用 padding 保证图片的长宽比应该是最广为人知的方式(这个技巧的首发于此),如果要实现 16:9 的比例,你可以这么做:
 
.aspect-ratio-16-9 {
 
  position: relative;
 
}
 
.aspect-ratio-16-9::before {
 
  display: block;
 
  padding-top: 56.25%; /* 9 / 16 * 100% */
 
  content: "";
 
}
 
.aspect-ratio-16-9-content {
 
  position: absolute;
 
  top: 0;
 
  right: 0;
 
  bottom: 0;
 
  left: 0;
 
}
 
HTML 结构如下:
 
<div class="aspect-ratio-16-9">
 
  <div class="aspect-ratio-16-9-content">
 
    This box will have a 16:9 aspect ratio.
 
  </div>
 
</div>
 
如果只有几种横纵比还好,但你要做的是网格布局的图片流,就会遇到各种各样尺寸的图片,这个方法明显不能解决问题.
 
该自定义属性 API 上场了,让我们来实现一个固定长宽比的图片容器吧!
 
.my-image-wrapper {
 
  /* 自定义属性
 
   * 长宽比 16:9 中的 16
 
   * 长宽比 16:9 中的 9  */
 
  --my-image-wrapper-w: 1; 
 
  --my-image-wrapper-h: 1;
 
  position: relative;
 
}
 
.my-image-wrapper::before {
 
  display: block;
 
  padding-top: calc(var(--my-image-wrapper-h, 1) / var(--my-image-wrapper-w, 1) * 100%);
 
  content: "";
 
}
 
.my-image-wrapper > img {
 
  position: absolute;
 
  top: 0;
 
  right: 0;
 
  bottom: 0;
 
  left: 0;
 
  height: 100%;
 
  width: 100%;
 
}
 
--my-image-wrapper-w 和 --my-image-wrapper-h 就是模块化的 CSS 接口,使用起来很灵活:
 
<div class="my-content my-image-wrapper" style="width:768px; --my-image-wrapper-w:4; --my-image-wrapper-h:3;">
 
  <img src="kitten.jpg" alt="A cute kitten">
 
</div>
 
现在我们的小猫可以正常显示了!
 
将这一步结合到自动化流程中的话,就能保证任何图片的长宽比了!
 
注意:我把这个功能封装为一个 npm 插件 css aspect ratio,欢迎围观.

如需转载,请注明文章出处和来源网址:http://www.divcss5.com/html/h63635.shtml