【问题标题】:Media Query scss breakpoints best practice媒体查询 scss 断点最佳实践
【发布时间】:2020-10-13 04:04:50
【问题描述】:

我与团队领导就媒体查询的使用发生了争执。 关于使用媒体查询,有两种方法(据我所知)。

方法一:

@media only screen and (max-width: 600px) {
  .container {
    width: 100%;
  }
}

@media only screen and (min-width: 600px) {
  .container {
    width: 90%;
  }
}

@media only screen and (min-width: 768px) {
  .container {
    width: 80%;
  }
}

方法二:

.container {
  @media only screen and (max-width: 600px) {
    width: 100%;
  }

  @media only screen and (min-width: 600px) {
    width: 90%;
  }

  @media only screen and (min-width: 768px) {
    width: 80%;
  }
}

我是一名初级开发人员,我发现第二种方法更易于使用和理解。然而我的老板告诉我使用第一种方法。老实说,我到处寻找使用我喜欢的第二种方法的示例项目,但找不到!

所以我的问题是为什么?

在我看来,如果我想在这个例子中添加一些类来包装容器,在方法 1 中我需要在每个断点中添加它,而在方法 2 中我只需要添加一次! 那么第一种方法如何是正确的做法呢?我错过了什么?

【问题讨论】:

标签: sass media-queries breakpoints


【解决方案1】:

偏爱第一种方法而不是第二种方法有一个原因和一个原因。向后兼容性。

https://caniuse.com/mdn-css_at-rules_media_nested-queries

在这一点上,除非您必须返回 2015 年之前的支持,否则不值得这样做,因为第二种方式确实更容易编写/理解。这就是为什么他们首先将支持放在官方规范中。

不过,以第二种方式编写它还有另一个好处。

在您的示例中,注意第二个方法中的.container 类不必重复。

虽然在此示例中看起来微不足道,但可以推断。想象一下 2 个包含数百甚至数千个类的样式表,一个专门使用方法 1,另一个使用方法 2。

问题:给定一种方法使用明显更少的字符来达到相同的结果,哪一种具有更小的文件大小?因此可能更快的加载时间?因此更好的用户体验?

【讨论】:

    【解决方案2】:

    为此,我制作了一个有用的辅助 mixin。

    $break-points: (
      mobile:     480px,
      tablet:     720px,
      desktopS:   960px,
      desktop:   1240px,
      desktopHD: 1920px
    );
    
    /** Helper to build @media query. Use named arguments only! */
    @mixin breakpoint-range($mode: screen, $from: false, $to: false, $extra: ()) {
      /** Checking arguments consistency */
      @each $key in ($from, $to) {
        @if $key and not map.has-key($break-points, $key) {
          @error "Available values for ($from, $to) args are: #{map.keys($break-points)}";
        };
      };
    
      /** Accumulator */
      $conditions: $mode;
    
      /** Combining breakpoints dependencies */
      @each $key, $value in (
        min-width: $from,
        max-width: $to,
      ) {
        @if $value {
          $modifier: if($key == 'max-width', -1px, 0px);
          $condition: " and (#{$key}: #{map.get($break-points, $value) - $modifier})";
          $conditions: string.insert($conditions, $condition, -1);
        }
      }
    
      /** Combining rest dependencies */
      @each $key, $value in $extra {
        $condition: " and (#{$key}: #{$value})"
      }
      
      /** Building final media query */
      @media #{$conditions} { @content; }
    }
    
    

    及用法:

    .element {
      /** Both bp arguments */
      @include breakpoint-range($from: mobile, $to: desktop) {
        /* Result: @media screen and (min-width: 480px) and (max-width: 1240px) */
      }
      /** One bp argument */
      @include breakpoint-range($to: desktop) {
        /* Result: @media screen and (max-width: 1240px) */
      }
      /** Just changing view mode */
      @include breakpoint-range($mode: print) {
        /* Result: @media print */
      }
      /** Or add anything else */
      @include breakpoint-range(
        $from: mobile, 
        $to: desktop, 
        $extra: (orientation: landscape)
      ) {
        /* Result: @media screen 
                      and (min-width: 480px) 
                      and (max-width: 1240px)
                      and (orientation: landscape)
        */
      }
    }
    

    【讨论】:

      【解决方案3】:

      非常好的问题,我认为这值得一个完整的话题,这个答案有助于@Unbrand 分享的所有内容。

      在决定哪个更好或最佳实践之间,我认为这里没有对错之分。坚持一个并不意味着一切都是正确的,这完全取决于造型师习惯的方法,最重要的部分是它的使用方式,成败都在这里。

      我想你已经知道并熟悉这两种方法的最终编译 CSS,当然最终的 bundle 大小也是优化的一个考虑因素。

      这就是方法2似乎失去意义的地方。

      方法 2 SCSS

      .container {
        width: 100%;
        
        @media screen and (min-width: 768px) {
          width: 50%;
        }
      
        &.red {
          @media screen and (min-width: 768px) {
            background: red;
            width: 75%;
          }
        }
      }
      
      

      这就是上面的 CSS 的编译方式,你可能会清楚地看到重复的字符串。扩大到实际项目,这可能是需要考虑的事情。

      方法 2 CSS

      .container { width: 100%; }
      
      @media screen and (min-width: 768px) {
        .container {
          width: 50%;
        }
      }
      @media screen and (min-width: 768px) {
        .container.red {
          background: red;
          width: 75%;
        }
      }
      

      M1,您将主要在旧项目中看到,可能会回到 2015 年之前,并且可能每个响应式查询都将位于单独的文件中。例如:

      responsive.mobile.scss

      @media screen and (max-width: 768px) {
        // All the stuff
      }
      

      responsive.tablet.scss

      @media screen and (min-width: 768px) and (max-width: 1024px) {
        // All the stuff
      }
      

      过去,我处理过一个项目,当您有 4 个响应式查询(另外,视网膜或纵向/横向它自己的位置)时,像这样的响应式事情变成了一场噩梦。你有很大的胆量来维护这样一个项目,你不会知道一个变化可能会影响其他的,并且由于某种原因你的客户改变了主意。在这种情况下,他也想给手机申请头像平板的样式,相信你知道这会导致什么。

      所以,M2 节省了一天。

      在 Web 应用程序的现代时代,事情变得“组件化”,我认为 M1 不再有帮助,出于某种原因,您会看到很多 FE 教程出现M2,原因很简单。它很干净,直截了当。忘记在响应式上下文之间切换,这种方法证明了它对 FE 家伙适应他的风格的方式很有帮助。

      方法 2 与新手/小伙子

      而且由于它的简单,M2 变得熟悉,直到它的目的出错。

      实际上,M1 是关于在多个地方/文件中拥有样式。每个响应式样式都位于自己的文件中,M2 是关于组件样式的,其中所有样式都位于一个位置。

      想想这个场景,这也成为维护的噩梦:

      响应式查询混合不当的方法 2

      .container {
        width: 100%;
      
        .button {
          background: red;
      
          @media screen and (min-width: 768px) {
            background: green;
          }
        }
      
        &.red {
          background: red;
          
          @media screen and (min-width: 768px) {
            background: darken(red, .15);
            width: 75%;
          }
        }
        
        @media screen and (min-width: 768px) {
          width: 50%;
        }
      }
      

      响应式查询混合良好的方法2

      
      .container {
        width: 100%;
      
        .button {
          background: red;
        }
      
        &.red {
          background: red;
        }
        
        @media screen and (min-width: 768px) {
          width: 50%;
      
          .button {
            background: green;
          }
      
          &.red {
            background: darken(red, .15);
            width: 75%;
          }
        }
      }
      

      第一个区块是新手在第一次尝试时会尝试 M2,但无法识别最终结果。该示例仅附带一个媒体查询,请考虑多个查询。

      当然第二个是用M2体验过造型的人,它清晰且易于维护。

      就我个人而言,我是曾经与M1合作的人,现在在我的作品中完全转向M2。我的大部分项目样式的比例为 7:3,其中 70% M2 应用于特定组件,30% M1 应用于全局/通用样式。我发现这是最好的。更不用说现在我们还让 JCSS 或样式组件进入了游戏。

      如前所述,您的团队负责人可能是一个习惯于在方法 1 中看到 CSS 的人,他有自己的观点。这完全取决于您的特定项目范围,哪种方法可能比另一种更好。

      【讨论】:

      • 感谢您的回答,很有帮助!
      【解决方案4】:

      我认为这是一个很好的问题,我经常觉得这种分歧是由习惯于在 SASS 之前的生活并拒绝进入 SASS 和嵌套 CSS 的新时代的老派程序员造成的。

      方法一

      优点

      您可以将每个用于断点的媒体查询放在一个位置,以便 当您想要进行多项更改时,更容易找到诊断 到页面模板。

      缺点

      这很混乱,你最终会得到多个类声明 这个地方,所以当涉及到编辑一个元素或添加一个新元素时 元素到 HTML 中,你最终不得不跨多个编辑 CSS 难以追踪的区域。

      它需要大量上下滚动才能找到媒体 查询有问题,然后编辑该单个类元素。

      方法二

      优点

      所有东西都放在一个地方,很容易找到 类并编辑其中使用的所有断点。

      还可以快速添加新断点以应用快速修复

      一目了然也更容易阅读和理解。

      缺点

      老派开发者可能不喜欢它!

      有时候不好。如果你有一个固定的模板并且你知道 它不会改变。为整个页面放置整个 CSS 或 区域使它更容易使用。您可以编辑多个类 一个断点都在一个地方。

      结论

      视情况而定。我不认为这是我的方式或高速公路类型的场景,它是两者的混合。

      在构建组件时,您通常希望像 方法 1 那样将 CSS 保持在一个块中。但是,当您要诊断已组合在一起并为特定元素插入单个断点的整个站点时,使用 方法 2 开始变得更有意义。

      我发现,我们创建的网站越多,我就越善于找出最适合这种情况的方法,而上述规则往往会引导我朝着正确的方向前进。

      【讨论】:

        猜你喜欢
        • 2015-10-18
        • 1970-01-01
        • 1970-01-01
        • 2021-09-23
        • 1970-01-01
        • 2013-05-10
        • 1970-01-01
        • 2017-04-12
        • 1970-01-01
        相关资源
        最近更新 更多