likes
comments
collection
share

从案例入门Sass适配PC端和移动端样式

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

前言

有时候我们开发一个布局样式比较简单的页面,如果它需要同时兼容移动端和PC端的展示,我们一般都会考虑是否可以用一套样式代码来完成并考虑其是否易于维护。例如一些企业官网它只用于展示一些信息,可能不同端的业务逻辑上也都只有登录和注册等功能,而我们需要调整的只有在移动端和PC端两种不同的样式布局。这时我们可以结合Sass的一些特性来帮助我们优雅的实现。

我们可以先来看下实际的案例 小鹏汽车海外官网 的效果:

前置知识了解

这里我们会用到Sass的 @mixin、@include、@content、@media 这几个指令和它提供的插值语法、变量就可以实现了。

我们先来了解下 @mixin、@include、@content

// 通过 @mixin 定义个混合指令
@mixin large-text {
    font-size: 24px;
    font-weight: 600;
}
// 混合指令还可以当做函数方法接收参数来使用,并且可以给参数设定默认值
@mixin set-border($color, $width: 1px, $style: solid) {
    border: $width $style $color;
    // 我们也可以在mixin混合指令中通过@content向其允许导入额外样式内容
    // 即额外的样式部分将会出现在@content标志的地方
    @content;
}


// 接着可以通过 @include 指令引用我们刚刚定义的 large-text、set-border,到我们需要的位置复用
.page-title {
    @include large-text;
    @include set-border(blue);
    // other css...
}
.username {
    @include large-text;
    @include set-border(red, 5px) {
        border-radius: 15px;
    };
    // other css...
}

上述示例的 .page-title.username样式会编译成如下:

.page-title {
    font-size: 24px;
    font-weight: 600;
    border: 1px solid blue;
}
.username {
    font-size: 24px;
    font-weight: 600;
    border: 5px solid red;
    border-radius: 15px;
}

接着看看Sass中的 @media指令,它和css中的用法是一样的,只是增加了额外的功能:允许在css规则中进行嵌套。例:

.sidebar {
  @media (max-width: 991px) {
    background: red;
  }
}

// 它会编译为如下:
@media (max-width: 991px) {
  .sidebar {
    background: red;
  } 
}

插值语句:#{}: 可以让我们在选择器或属性名中使用变量 例:

@mixin setColor($attr, $val) {
    #{$attr}-color: $val; 
}
.page-container{
  border: 5px solid black;
  @include setColor(border, blue);
  @include setColor(background, yellow);
}

// 上述.page-container样式会被编译为
.page-container{
  border: 5px solid black;
  border-color: blue;
  background-color: yellow;
}

实战应用

了解了上述的一些知识点后,我们就可以进入正题,看看如何通过这些特性来实现适配PC和移动端的样式。

1.我们可以先抽取一个mixin.scss文件,里面定义了公共的混入指令,方便其他页面样式引入使用:

// mixin.scss

// pcSize指令用于我们编写PC端样式时防止插件进行rem/vw的单位转换
@mixin pcSize($prop, $val) {
  /**
      如果你用的postcss-px2rem,通过 / *no* / 这个注释就可以让其跳过这行单位转换
      如果你用的postcss-px-to-viewport 通过 / *px-to-viewport-ignore* / 即可跳过转换
  **/
  #{$prop}: $val; /*no*/
}

@mixin pcContent {
  @media (min-width: 992px) {
    @content;
  }
}

@mixin mobileContent {
  @media (max-width: 991px) {
    @content;
  }
}

2.有了上述封装好的几个关键的指令,接着我们到对应的页面就可以通过 @include 来引入使用了,比如区分PC和移动端的背景图样式:

//common.scss

// 假设我们的PC和移动端的背景图是两张不同尺寸的图,我们设置最外层版心盒子时就可以这么写:
.page-container {
  @include pcContent {
    // 屏幕宽度大于992时的样式
    min-height: 100vh;
    background: url('pc-bg.png') top center no-repeat;
    background-size: cover;
  }
  @include mobileContent {
    // 屏幕宽度小于991时的样式
    min-height: 100vh;
    background: url('mobile-bg.png') top center no-repeat;
    background-size: cover;
  }
}

// 上述.page-container的样式其实就是编译成:
@media (min-width: 992px) {
    .page-container {
        min-height: 100vh;
        background: url('pc-bg.png') top center no-repeat;
        background-size: cover;
    }
}
@media (max-width: 991px) {
    .page-container {
        min-height: 100vh;
        background: url('mobile-bg.png') top center no-repeat;
        background-size: cover;
    }
}

3.上述都属于公共部分的样式,当我们需要细的节调整某一个元素的PC和移动端样式时:

// login.vue

// 移动端和pc端可以通用的样式可以直接写
.login-container{
    // css code...
    border: 1px solid #0094ff; /*no*/ 
}

// 当需要细致区分的时候通过引入的 pcContent 和 mobileContent 即可:
@include pcContent {
    .login-container{
        // pc端 css code...
        //当我们希望我们pc端的单位不被postcss插件所转换时,就可以用到 pcSize 指令了
        @include pcSize(width, 600px);
        @include pcSize(height, 240px);
        @include pcSize(padding, 20px);
        @include pcSize(font-size, 18px);
    }
}

@include mobileContent {
    .login-container{
        // 移动端 css code...
        width: 400px;
        height: 200px;
        padding: 20px;
        font-size: 16px;
    }
}

一个demo示例,可以查看详情通过改变视口的宽度来查看效果

结语

当然如果在较为复杂的页面样式布局场景下,即两种样式布局或业务逻辑等区别差距过大时,我们为了提升可维护性,必要时还是将其拆分成不同的样式文件维护比较好。 Sass是一门非常强大的CSS拓展语言,上述特性只是它的冰山一角,如果想要了解学习更多可以查阅其官网深入学习。

这里我也是结合自己接触过的实际应用经验并将其分享了出来,希望对大家有所帮助。然后这也是我第一次发文,有写错的地方或者不好的地方,或者更不错的方案和案例等可以私信或者评论进行沟通交流(#^.^#),相互学习进步~!🎉