本人笔记地址

#目录

利用视口单位适配页面

对于移动端开发来说,最为重要的一点是如何适配页面,实现多终端的兼容,不同的适配方式各有千秋,也各有缺点。 就主流的响应式布局、弹性布局来说,通过 Media Queries 实现的布局需要配置多个响应断点,而且带来的体验也对用户十分的不友好:布局在响应断点范围内的分辨率下维持不变,而在响应断点切换的瞬间,布局带来断层式的切换变化,如同卡带的唱机般“咔咔咔”地一下又一下。 而通过采用rem单位的动态计算的弹性布局,则是需要在头部内嵌一段脚本来进行监听分辨率的变化来动态改变根元素字体大小,使得 CSS 与 JS 耦合了在一起。 有没有办法能够解决这样的问题呢? 答案是肯定的,通过利用视口单位实现适配的页面,是既能解决响应式断层问题,又能解决脚本依赖的问题的。

做法一:仅使用vw作为CSS单位

在仅使用 vw 单位作为唯一应用的一种 CSS 单位的这种做法下,我们遵守: 1.对于设计稿的尺寸转换为vw单位,我们使用Sass函数编译

  1. //iPhone 6尺寸作为设计稿基准
  2. $vm_base: 375;
  3. @function vw($px) {
  4. @return ($px / 375) * 100vw;
  5. }

2.无论是文本还是布局高宽、间距等都使用 vw 作为 CSS 单位

  1. .mod_nav {
  2. background-color: #fff;
  3. &_list {
  4. display: flex;
  5. padding: vm(15) vm(10) vm(10); // 内间距
  6. &_item {
  7. flex: 1;
  8. text-align: center;
  9. font-size: vm(10); // 字体大小
  10. &_logo {
  11. display: block;
  12. margin: 0 auto;
  13. width: vm(40); // 宽度
  14. height: vm(40); // 高度
  15. img {
  16. display: block;
  17. margin: 0 auto;
  18. max-width: 100%;
  19. }
  20. }
  21. &_name {
  22. margin-top: vm(2);
  23. }
  24. }
  25. }
  26. }

3.1物理像素线(也就是普通屏幕下 1px ,高清屏幕下 0.5px 的情况)采用 transform 属性 scale 实现。

  1. .mod_grid {
  2. position: relative;
  3. &::after {
  4. // 实现1物理像素的下边框线
  5. content: '';
  6. position: absolute;
  7. z-index: 1;
  8. pointer-events: none;
  9. background-color: #ddd;
  10. height: 1px;
  11. left: 0;
  12. right: 0;
  13. top: 0;
  14. @media only screen and (-webkit-min-device-pixel-ratio: 2) {
  15. -webkit-transform: scaleY(0.5);
  16. -webkit-transform-origin: 50% 0%;
  17. }
  18. }
  19. ...
  20. }

4.对于需要保持高宽比的图,应改用 padding-top 实现

  1. .mod_banner {
  2. position: relative;
  3. padding-top: percentage(100/700); // 使用padding-top
  4. height: 0;
  5. overflow: hidden;
  6. img {
  7. width: 100%;
  8. height: auto;
  9. position: absolute;
  10. left: 0;
  11. top: 0;
  12. }
  13. }

做法二:搭配vw和rem,布局更优化

这样的页面虽然看起来适配得很好,但是你会发现由于它是利用视口单位实现的布局,依赖于视口大小而自动缩放,无论视口过大还是过小,它也随着视口过大或者过小,失去了最大最小宽度的限制。 当然,你可以不在乎这样微小的不友好用户体验,但我们还是尝试下追求修复这样的小瑕疵吧。 于是,联想到不如结合rem单位来实现布局?rem 弹性布局的核心在于动态改变根元素大小,那么我们可以通过:

  1. 给根元素大小设置随着视口变化而变化的 vw 单位,这样就可以实现动态改变其大小。
  2. 限制根元素字体大小的最大最小值,配合 body 加上最大宽度和最小宽度

这样我们就能够实现对布局宽度的最大最小限制。因此,根据以上条件,我们可以得出代码实现如下:

  1. // rem 单位换算:定为 75px 只是方便运算,750px-75px、640-64px、1080px-108px,如此类推
  2. $vm_fontsize: 75; // iPhone 6尺寸的根元素大小基准值
  3. @function rem($px) {
  4. @return ($px / $vm_fontsize ) * 1rem;
  5. }
  6. // 根元素大小使用 vw 单位
  7. $vm_design: 750;
  8. html {
  9. font-size: ($vm_fontsize / ($vm_design / 2)) * 100vw;
  10. // 同时,通过Media Queries 限制根元素最大最小值
  11. @media screen and (max-width: 320px) {
  12. font-size: 64px;
  13. }
  14. @media screen and (min-width: 540px) {
  15. font-size: 108px;
  16. }
  17. }
  18. // body 也增加最大最小宽度限制,避免默认100%宽度的 block 元素跟随 body 而过大过小
  19. body {
  20. max-width: 540px;
  21. min-width: 320px;
  22. }

小结

相对于做法一,个人比较推崇做法二,有以下两点原因: 第一,做法二相对来说用户视觉体验更好,增加了最大最小宽度的限制; 第二,更重要是,如果选择主流的rem弹性布局方式作为项目开发的适配页面方法,那么做法二更适合于后期项目从 rem 单位过渡到 vw 单位。只需要通过改变根元素大小的计算方式,你就可以不需要其他任何的处理,就无缝过渡到另一种CSS单位,更何况vw单位的使用必然会成为一种更好适配方式,目前它只是碍于兼容性的支持而得不到广泛的应用。

后语

这是笔者在偶然中阅读到[翻译]使用VH和VW实现真正的流体排版这一篇文章得到的感悟与成果,也满心欢喜地期待这篇文章同样能够带给读者一些启发,并提出一些的vw单位使用秘笈来交流交流~:) 原文:凹凸实验室 https://aotu.io/notes/2017/04/28/2017-4-28-CSS-viewport-units/