likes
comments
collection
share

构建响应式布局,CSS该有的视角--CSS篇(二)

作者站长头像
站长
· 阅读数 28

传统布局的缺陷

在网页设计中,各元素的相对位置影响着整体页面的美观。为了方便用户使用,许多产品的官网都会开发PC端和手机端。但是,传统的布局设计不足以满足市面上形形色色的电子设备,导致一个页面在不同设备上显示的效果天差地别。难道我们要为每一种不同的设备打造不同的网页吗?显然这么做是不明智的。

传统的布局采用px作为单位描述元素的几何属性,例如长、宽、高等等。这么写在许多地方会有问题,可以看看下面的例子。

构建响应式布局,CSS该有的视角--CSS篇(二) 构建响应式布局,CSS该有的视角--CSS篇(二)

这是一个简单的天气预报例子,使用的是px作为单位。在设备是iPhone6/7/8的情况下,页面元素的布局还算协调。但是换成iPad Pro,效果就极其拉跨。

为了解决这个布局,我们需要采用响应式布局,让页面元素的几何属性响应不同设备屏幕的几何属性。

响应式设计

在响应式设计当中,remem是重要的工具之一。在此基础上,我们还需要提供媒体查询的手段来识别用户设备屏幕属性,以便动态设置上级元素字体大小。

一、认识rem和em

响应式布局,简单来说,就是利用父元素属性影响子元素属性的特性。采用一个弹性单位,使得我们改变根元素(通常是html标签)的某些数据就能够影响下面所有子元素的几何属性。

在响应式设计中,remem是两个重要的单位。

rem全称是root em,用来描述子元素属性是相对于根元素字体大小。例如根元素字体大小为20px,如果某个子元素宽度为1rem,那么表示子元素宽度实际为20px。

em表明子元素属性是相对于父元素,这常常用于父子元素之间相对属性需要严格绑定的场景。例如显示文章的场景,让文章标题和正文的字体能够根据父元素的大小自动调整。看下面一个例子:

构建响应式布局,CSS该有的视角--CSS篇(二) 构建响应式布局,CSS该有的视角--CSS篇(二)

这里的标题和段落字体大小虽然同步变化,但是字体的大小不适应屏幕的变化。这是因为我们还不能识别用户设备屏幕宽度,可以考虑CSS的媒体查询或JS实现

既然是考虑灵活的布局方式,在适当的地方使用%单位也是一个明智的选择。

二、媒体查询

媒体查询是一种CSS功能,开发者可以针对不同的设备制定不同的样式规则。

基本语法

媒体查询的基本语法如下:

//参数为条件,例如max-width : 800px
@media not|only mediatype and (expressions) {
  //CSS代码
}

其中mediatype可以省略,默认是为screen expression是一组表达式,用于指定媒体查询生效的条件。

示例

假设我们需要针对不同屏幕来应用不同的样式,可以这样写:

/* 默认样式 */
html {
  font-size: 16px; /* 默认字体大小 */
}

/* 当屏幕宽度小于等于 600px 时 */
@media (max-width: 600px) {
  html {
    font-size: 14px; /* 减小字体大小 */
  }
}

/* 当屏幕宽度大于等于 900px 时 */
@media (min-width: 900px) {
  html {
    font-size: 18px; /* 增加字体大小 */
  }
}

在这个例子中,我们定义了三个场景:

  • 默认情况下,字体大小 16 px
  • 屏幕宽度 <=600 px 字体大小变为 14 px
  • 屏幕宽度 >=900 px 字体大小变为 18 px

结合rem

rem+媒体查询是实现响应式布局的一个常用方案。一般来说,以下央视推荐放入媒体查询:

  1. 字体大小
  2. 间距
  3. 布局元素的高度和宽度
  4. 图片的宽度
  5. 元素的可见性

上面天气预报的例子部分样式代码长这样:

//预报框
.group{
    height: 80px;
    line-height: 40px;
    /* rgba(245, 242, 242, 0.3) */
    background-image:repeating-linear-gradient(to right,#404222,#98adad)       ;
    font-size: 13px;
    padding: 0 10px;
    margin-bottom: 10px;
    border-radius: 5px;
    position: relative;
    opacity: 0.8;
}

也就是这个界面: 构建响应式布局,CSS该有的视角--CSS篇(二)

我们采用rem+媒体查询的方式改写代码后:


@media (min-width: 768px) { /* 对于较大的屏幕 */
  html {
    /*设置根字体大小*/
    font-size: 40px; 
  }

  .group {
    height: 4rem;
    line-height: 2rem; 
    background-image: repeating-linear-gradient(to right, #404222, #98adad);
    font-size: 0.65rem; 
    padding: 0 0.5rem; 
    margin-bottom: 0.5rem; 
    border-radius: 0.25rem; 
    position: relative;
    opacity: 0.8;
  }

  .temp {
    font-size: 0.65rem; 
    display: block;
    margin: 0;
    color: rgb(255, 255, 255);
  }
}

@media (max-width: 767px) { /* 对于较小的屏幕 */
  html {
    font-size: 20px; 
  }

  .group {
    height: 4rem;
    line-height: 2rem; 
    background-image: repeating-linear-gradient(to right, #404222, #98adad);
    font-size: 0.65rem; 
    padding: 0 0.5rem; 
    margin-bottom: 0.5rem; 
    border-radius: 0.25rem; 
    position: relative;
    opacity: 0.8;
  }

  .temp {
    font-size: 0.65rem; 
    display: block;
    margin: 0;
    color: rgb(255, 255, 255);
  }
}

构建响应式布局,CSS该有的视角--CSS篇(二)

这里的字体大小实���为26px,如果不使用媒体查询,那么将默认所有设备都一致,采用默认字体大小16px。

在一般情况下,媒体查询中我们会写入需要响应式布局的元素属性,同时还会在全局提供一份默认样式,默认样式包含所有需要用到的样式。

媒体查询能够覆盖全局的默认样式。

在实际项目中,通常会选择一些标准的断点值来适配常见的设备尺寸,例如320px、480px、768px、1024px等。此外,为了提高代码的可维护性,还将常用的断点值定义为CSS变量或者使用预处理器(如Sass)来管理这些值。

三、JS实现响应式布局

rem+媒体查询的方式的确实是十分简单,但是对于断点的选择,也就是媒体查询的条件是一个不小的问题。如果我们想实现更具细粒度的响应式布局,那么单纯的CSS就满足不了需求。

我们需要考虑JS的方式来实现响应式布局。

具体思路:

  • 获取用户设备屏幕宽度
  • 按比例计算出对应根字���大小
  • 使用rem编写css

可以看到这个方法也十分简单,核心就是获取用户屏幕宽度,通过比例设置根字体大小。不过既然是动态的获取,我们还需要添加DOMContentLoaded事件。

具体代码:

//实现js读取当前用户屏幕宽度 设置根字体大小
(function(doc){
    //根节点
    let docEl = doc.documentElement;
    //设置时机 DOM结构加载完毕
    doc.addEventListener('DOMContentLoaded',recalc)
    function recalc() {
        //获取设备宽度 window上没有clientWidth 不带边框 offsetWidth 带边框的宽度
        let width = docEl.clientWidth;
        //设置docEl的字体大小
        docEl.style.fontSize = 20 * (width/320) + 'px';
    }

})(document)//文档对象

实现这样一个小功能十分简单,但是却可以得到十分高效完美的体验。

对于CSS部分,我们只需要在编写全局样式时使用rem作为单位即可。

lib-flexible插件

lib-flexible插件能够解决移动端的适配问题。

1.引入

在项目的入口文件(main.js)中引入即可使用。

npm i lib-flexible --save

如果使用的是commonJS模块化,可以这样做:

require('lib-flexible/flexible')
2.原理

lib-flexible的核心思想是基于屏幕宽度动态设置根字体的大小,通常会将字体大小设置为屏幕的1/10。

3.结合PostCSS

如果觉得直接在样式中使用rem不方便阅读,还可以考虑另一个插件系统:PostCSS。它用于处理CSS代码。我们考虑使用其内部的postcss-px-to-viewport,这是一个将px单位自动转换为rem的插件。

  • 安装
npm install postcss-px-to-viewport --save-dev
  • 配置PostCSS 在项目的根目录创建或者修改postcss.config.js文件:
module.exports = {
  plugins: {
    'postcss-px-to-viewport': {
      viewportWidth: 375, // 视口宽度,对应设计稿的宽度
      unitPrecision: 5, // 转换后的精度,即小数点位数
      viewportUnit: 'rem', // 希望转换后的单位
      selectorBlackList: ['.ignore-'], // 可以忽略某些样式
      minPixelValue: 1, // 小于或等于1px则不转换为rem
      mediaQuery: false, // 是否在媒体查询的css代码中也转换px为rem
      replace: true, // 是否转换后删除原样式
      exclude: undefined, // 可以设定忽略某些文件夹下的文件,例如'node_modules'
      include: undefined, // 包含某些文件夹下的文件,例如'app'
    },
  },
};

如此一来,我们可以按照传统编写css的方式写,利用lib-flexible+postcss,轻松实现移动端的适配。

总结

上面分享了rem+媒体查询JS+插件两种实现响应式布局的方式,再来进行一次简单对比:

1.使用场景

  • rem单位 + 媒体查询

需要根据设备屏幕大小调整字体大小和其他元素时。

只需要简单动态的响应式布局时。

  • lib-flexible + PostCS

需要高度的动态响应式布局,如像素适配等。

大型项目,需要自动计算和换算单位。

2.优缺点

  • rem单位 + 媒体查询

    • 优点:

      直观且利于理解,设备的针对性强,不依赖于第三方库。

    • 缺点:

      断点频繁时,代码冗杂。

  • lib-flexible + PostCS

    • 优点:

      自动化程度高,适配效果好。

    • 缺点:

      额外的工具学习成本,某些情况下会过度适配。

    以上就是简单总结,如果你觉得本文对你有帮助,请点个赞!这将是我持续创作的动力,感谢。

转载自:https://juejin.cn/post/7396523906277277705
评论
请登录