Stepping away from Sass

收藏待读

Stepping away from Sass

I try to rebuild or redesign my website at least once every year, it’s a great way to keep up to date with HTML and CSS advances as well as workflows and site generators. I launched the latest version last month moving from Jekyll and Github pages to Eleventy and Netlify.

I also unintentionally, (at least at first) removed all traces of Sass from my codebase. This was not something I set out to do but the more I looked at my old Sass files the more I questioned whether it was adding value to my site, or just an extra level of complexity and dependency. CSS has evolved over recent years and the problems that lead me to Sass in the first place seem to be less of an issue today.

The knock on effect of this was removing media queries. As I moved towards some of the more modern features of CSS the need to target specific screen sizes with unique code was removed.

What problems was Sass solving?

When I first starting to learn about Sass (around 5 or 6 years ago) I was skeptical, but as I built more and more responsive websites I began to realise how much time I could save by having reusable pieces of logic from Sass functions and mixins. It also became apparent that as devices, viewports and themes changed using variables made implementing updates much easier to handle.

Things I used Sass for:

  • Layout
  • Variables
  • Typography

1) Layout

Layout has been a longstanding source of frustration with CSS. This coupled with a move to fluid or responsive layouts was a key factor in my initial decision to use Sass to create a CSS grid.

Before Sass

I can still remember my first attempt at building a responsive grid layout in CSS, it involved creating a set of utility classes for each column and then polluting the markup with non semantic class names like col-span-1 and col-span-4.

.col-span-3 {
  float: left;
  width: 24%;
  margin-left: 1%;
}

.col-span-4 {
  float: left;
  width: 32.3%;
  margin-left: 1%;
}

.col-span-5 {
  float: left;
  width: 40.6%;
  margin-left: 1%;
}

By using a Sass mixin paired with variables I was able to remove utility classes like the ones above, and also create more flexible layouts by changing the $gridColumns variable.

My first grid mixin:

@mixin grid($colSpan, $gridColumns: 12, $margin: 1%,) {
  $unitWidth: $gridColumns / $colSpan;
  float:left;
  width: (100 - $unitWidth * $margin) / $unitWidth;
  margin: 0 $margin/2;
}

Implemented like this:

.sidebar {
	@include grid(3);
}

.main-content {
	@include grid(9);
}

@media only screen and (max-width: 480px) {

  .sidebar {
    @include grid(12);
  }

  .main-content {
    @include grid(12);
  }

}

CSS grid

The introduction of CSS Grid removes the need for any of this, you no longer need to build a grid system with utility classes, in Sass or any other processor. Rachel Andrew says it best here…

You don’t need a tool that helps you make it look like you have a grid, you actually have a grid!

The code below creates a responsive layout that adapts based on the min and max width of the content, not on pre set device sizes.

.project {
  display: grid;
  grid-template-columns: repeat( auto-fill, minmax(12em, 1fr) );
  grid-gap: 1em;
}

Moving from a Sass based grid to CSS grid was a relatively pain free experience, not only did it reduce my dependency on Sass it also allowed me to create a much flexible codebase, opened up wider design possibilities and allowed me to structure the site around content not media queries.

The obvious downside to switching to native CSS for my layout is the limited browser support, or so I thought. Grid is currently supported in most modern browsers and with prefixes, IE11 and IE10 too. auto-fill and auto-fit have less support, but this can be easily rectified with a feature query.

2) Variables

A variable is a value that is likely to change, in terms of CSS a variable is something I didn’t know I needed until I had it. Nowadays most of my projects follow the ITCSS methodology and so start of with a settings file containing the project variables. Usually I set variables up for fonts, colours and media queries.

My old Sass set up:

/* COLORS */
$colors: (
  "black": #2a2a2a,
  "white": #fff,
  "grey-light": #ccc7c3,
  "grey-dark": #2a2a2a,
  "accent": #ffa600,
  "off-white": #f3f3f3,
  "sky-blue": #ccf2ff
 );

/* BREAKPOINTS */
$breakpoints: (
  "break-mobile": 290px,
  "break-phablet": 480px,
  "break-tablet": 768px,
  "break-desktop": 1020px,
  "break-wide": 1280px
);

/* TYPOGRAPHY */
$font-stack: (
  decorative: #{'oswald', Helvetica, sans-serif},
  general: #{'Helvetica Neue', Helvetica, Arial, sans-serif}
);

Using variables or maps like this allowed me to make site wide changes quickly and easily. It also helps prevent the build up of multiple shades, colour variations and anomalies common in large code bases, particularly for hover states, shadows, borders etc.

For example:

.button {
  background-color: #4CAF50; /* Green */
}

.button:hover {
  background-color: #3F8C42; /* Dark Green */
}

.button:active {
  background-color: #266528; /* Darker Green */
}

Can be rewritten using Sass variables and colour functions to:

$button-colour: #4CAF50;

.button {
  background-color: $button-colour; 
}

.button:hover {
  background-color: darken($button-colour, 20%);
}

.button:active {
  background-color: darken($button-colour, 50%);
}

So whats changed?

CSS custom properties can do more than just replace pre processor variables, they have the added bonus of being updated dynamically (instead of compiled at build). This allows values to be altered at run time with Javascript and to be scoped without the need for mixins and functions to outwit the cascade.

:root {
  --button-color: #4CAF50;
}

.button {
  background-color: var(--colour-color);
}

header 
.button {
  --button-color: #000000;
  background-color: var(--colour-color);
}

Colour manipulations like those available in Sass are also available in native CSS using the color-mod function.

:root {
  --button-color: #4CAF50;
}

.button:hover {
  color: color-mod(var(--button-color) tint(50%));
}

Unfortunately this is still at public working draft stage so for the time being I decided to remove effects like this and replace them with full colour changes and text effects.

.button {
  background: var(--colour-dark);
}

.button:hover {
  background: var(--colour-bright);
  text-decoration: underline;
}

However if you really want to use them there are a few PostCSS workarounds about including postcss-color-mod-function .

3) Typography

Finally typography, in previous code bases I was using Sass to create responsive typography and spacing. Mixins like the one below allowed me to easily automate changes for different screen sizes and devices.

@mixin typography($size) {
  
  font-size: $size;

  @include mq(break-desktop) {
    font-size: $size * 1.2;
  }

}

Today I use calc and viewport units to perform theese calculations in native CSS instead.

:root {
   --font-size: calc(18px + 0.25vw)
}

body {
  font-size: var(--font-size);
}

In future

CSS is moving towards a more content lead spec, as well as CSS grid there is flexbox and sizing properties like min-content, max-content and fit-content as well as future developments like Subgrid from CSS Grid Layout Module Level 2.

All of these features make native CSS much more attractive to work with.

Further reading/listening

原文 : The Changelog

相關閱讀

免责声明:本文内容来源于The Changelog,已注明原文出处和链接,文章观点不代表立场,如若侵犯到您的权益,或涉不实谣言,敬请向我们提出检举。