Sass 使用總結

世界上最成熟、最穩定、最強大的專業級 CSS 擴展語言! - Sass 官網css

主要內容:html

  • Sass 使用總結
  • Bootstrap@4 關於 float 組件的實現

安裝

我本地結合 gulp+sass 自動化工具使用,主要以下:前端

npm install node-sass gulp-sass --save-dev
複製代碼

gulpfile.js 文件主要配置以下,詳情能夠參考這裏node

const { src, dest, watch } = require("gulp");
const sass = require("gulp-sass");
sass.compiler = require("node-sass");

function scss() {
  return src(scssGlobSrc)
    .pipe(sass({ outputStyle: "expanded" }).on("error", sass.logError))
    .pipe(dest("dist/sass"));
}

exports.scss = scss;
複製代碼

啓動:gulp scssgit

四種編譯排版

/*未編譯樣式*/
.box {
  width: 300px;
  height: 400px;
  &-title {
    height: 30px;
    line-height: 30px;
  }
}
複製代碼

nested 編譯排版格式github

/*命令行內容*/
sass style.scss:style.css --style nested

/*編譯事後樣式*/
.box {
  width: 300px;
  height: 400px;
}
.box-title {
  height: 30px;
  line-height: 30px;
}
複製代碼

expanded 編譯排版格式shell

/*命令行內容*/
sass style.scss:style.css --style expanded

/*編譯事後樣式*/
.box {
  width: 300px;
  height: 400px;
}
.box-title {
  height: 30px;
  line-height: 30px;
}
複製代碼

compact 編譯排版格式npm

/*命令行內容*/
sass style.scss:style.css --style compact

/*編譯事後樣式*/
.box {
  width: 300px;
  height: 400px;
}
.box-title {
  height: 30px;
  line-height: 30px;
}
複製代碼

compressed 編譯排版格式gulp

/*命令行內容*/
sass style.scss:style.css --style compressed

/*編譯事後樣式*/
.box {
  width: 300px;
  height: 400px;
}
.box-title {
  height: 30px;
  line-height: 30px;
}
複製代碼

靜默註釋

body {
  // 這種註釋內容不會出如今生成的css文件中
  color: #333;
  /* 這種註釋內容會出如今生成的css文件中 */
  padding: 0;
}
複製代碼
body {
  color: #333;
  /* 這種註釋內容會出如今生成的css文件中 */
  padding: 0;
}
複製代碼

使用變量

很是簡單明瞭,變量申明:$color: #4a4a4a;,變量引用:color: $color;,具體例子演示以下:bootstrap

$bg-color: #f90;
$font-color: #444;
body {
  background: $bg-color;
  color: $font-color;
}
.selected {
  border: 1px solid $font-color;
}
複製代碼
body {
  background: #f90;
  color: #444;
}

.selected {
  border: 1px solid #444;
}
複製代碼

嵌套 CSS 規則

文檔:在 Sass 中,你能夠像俄羅斯套娃那樣在規則塊中嵌套規則塊。sass 在輸出 css 時會幫你把這些嵌套規則處理好,避免你的重複書寫。

看個例子,基本就知道什麼意思:

ul {
  li {
    a {
      color: $font-color;
      &:hover {
        color: red;
      }
      &::after {
        content: "...";
      }
    }
  }
}
複製代碼
ul li a {
  color: #444;
}

ul li a:hover {
  color: red;
}

ul li a::after {
  content: "...";
}
複製代碼

夠簡潔,不過有一些嵌套規則,須要稍稍留意,好比:

  • 父選擇器的標識符&
  • 羣組選擇器的嵌套
  • 子組合選擇器和同層組合選擇器:>、+ 和 ~
  • 屬性嵌套

父選擇器的標識符

父選擇器的標識符&,記住&是爸爸,你能夠在爸爸的後邊,也能夠在爸爸的前邊,隨你,哈哈哈哈:

nav a {
  color: $font-color;
  /* Dad after */
  &:hover {
    color: red;
  }
  /* Dad before */
  .header & {
    color: #000;
  }
}
複製代碼
nav a {
  color: #444;
}

/* Dad after */
nav a:hover {
  color: red;
}

/* Dad before */
.header nav a {
  color: #000;
}
複製代碼

Dad 是爸爸們:nav a,什麼場景能用到Dad before?想一想nav a是通用樣式,我想給 header 組件單獨nav a的樣式,即.header nav a,即.header &

固然,還能夠這樣用:

.main {
  color: black;
  &-sidebar {
    border: 1px solid;
  }
}

// css
.main {
  color: black;
}

.main-sidebar {
  border: 1px solid;
}
複製代碼

羣組選擇器的嵌套

文檔例子:

.container {
  h1,
  h2,
  h3 {
    margin-bottom: 0.8em;
  }
}
nav,
aside {
  a {
    color: blue;
  }
}
複製代碼
.container h1,
.container h2,
.container h3 {
  margin-bottom: 0.8em;
}

nav a,
aside a {
  color: blue;
}
複製代碼

名字就已經告訴我們這個規則的要點是:羣組。大括號{前端的均可以是一個羣組,好比.container,好比nav, aside,不論多少。

作爲羣組的任何一員,有權利獲取子嗣,並且還得跟其餘羣組成員如出一轍,若 Ta 有 三個(h1, h2, h3)子嗣,那羣組的任何一員也得各自有三個子嗣;Ta 若是隻有一個(a)子嗣,即便羣組人不少,也得每一個成員一人一個。

演練:有三個組件header article footer,我但願字體顏色有默認值,連接例外,而且有 hover 變化。

.header,
.acticle,
.footer {
  color: $font-color;
  a {
    color: #999;
    &:hover {
      color: red;
    }
  }
}
複製代碼
.header,
.acticle,
.footer {
  color: #444;
}

.header a,
.acticle a,
.footer a {
  color: #999;
}

.header a:hover,
.acticle a:hover,
.footer a:hover {
  color: red;
}
複製代碼

子組合和同層組合

子組合選擇器 > 和同層組合選擇器 +、~,和 CSS 的規則一致。

/* 選擇article 後的同層全部 article 元素 */
article ~ article {
  border-top: 1px dashed #ccc;
}
/* 選擇nav元素後緊跟的article元素 */
nav + article {
  margin-top: 0;
}
/* 選擇article下的全部命中section選擇器的元素 */
article > section {
  background: #eee;
}
複製代碼

文檔例子:

article {
  ~ article {
    border-top: 1px dashed #ccc;
  }
  > section {
    background: #eee;
  }
  dl > {
    dt {
      color: #333;
    }
    dd {
      color: #555;
    }
  }
  nav + & {
    margin-top: 0;
  }
}
複製代碼
article ~ article {
  border-top: 1px dashed #ccc;
}

article > section {
  background: #eee;
}

article dl > dt {
  color: #333;
}

article dl > dd {
  color: #555;
}

nav + article {
  margin-top: 0;
}
複製代碼

嵌套屬性

規則:把屬性名從中劃線-的地方斷開,在根屬性後邊添加一個冒號:,緊跟一個{ }塊,把子屬性部分寫在這個{ }塊中。就像 css 選擇器嵌套同樣,sass 會把你的子屬性一一解開,把根屬性和子屬性部分經過中劃線-鏈接起來,最後生成的效果與你手動一遍遍寫的 css 樣式同樣:

nav {
  border: {
    style: solid;
    width: 1px;
    color: #ccc;
  }
}
nav {
  border: 1px solid #ccc {
    left: 0px;
  }
}

// css
nav {
  border-style: solid;
  border-width: 1px;
  border-color: #ccc;
}

nav {
  border: 1px solid #ccc;
  border-left: 0px;
}
複製代碼

一句話:我要把border-style裏的-打斷,拆散左右,並替換成:,從新使用{}嵌套使用,宗旨就是不破不立,有破纔有立,把全部重複的東西通通歸併,只寫關鍵部位。

@-Rules

@import 導入

在單獨使用 css 的 @import 規則導入文件,是不及 link 的效率,好比加載字體庫,有次在項目中就吃過這個虧,那會發誓打死我也不用這個規則。

sass 的@import 規則是在生成 css 文件時就把相關文件導入進來,因此,和 css 的@import沒有什麼關係,放心食用。

可是因爲 sass 兼容原生的 css,因此它也支持原生的 CSS@import,好比導入文件或者 url 是以 .css結尾的。

使用:

// 經常使用方法
@import "header";
@import "footer";

// 多個導入
@import "rounded-corners", "text-shadow";

// 嵌套導入
.blue-theme {
  @import "blue-theme";
}
複製代碼

若是將文件命名爲 _colors.scss,便不會編譯_colours.css 文件,可是導入時依然是@import "colors";

@media 媒體查詢

Sass 中 @media 指令與 CSS 中用法同樣,不過還容許其在 CSS 規則中嵌套,編譯時,@media 將被編譯到文件的最外層,包含嵌套的父選擇器。

.sidebar {
  width: 300px;
  @media screen and (orientation: landscape) {
    width: 500px;
  }
}

/* 拼接 and */
@media screen {
  .sidebar {
    @media (max-width: 1140px) {
      width: 960px;
    }
  }
  .other {
    @media (max-width: 640px) {
      width: 100%;
    }
  }
}
複製代碼
.sidebar {
  width: 300px;
}

@media screen and (orientation: landscape) {
  .sidebar {
    width: 500px;
  }
}

/* 拼接 and */
@media screen and (max-width: 1140px) {
  .sidebar {
    width: 960px;
  }
}

@media screen and (max-width: 640px) {
  .other {
    width: 100%;
  }
}
複製代碼

@extend

和其餘語言同樣,就是繼承。好比代碼中的.error,以及同級.intrusion,都會被繼承:

.error {
  border: 1px #f00;
  background-color: #fdd;
}
.error.intrusion {
  background-image: url("/image/hacked.png");
}
.seriousError {
  @extend .error;
  border-width: 3px;
}
複製代碼
.error,
.seriousError {
  border: 1px #f00;
  background-color: #fdd;
}

.error.intrusion,
.intrusion.seriousError {
  background-image: url("/image/hacked.png");
}

.seriousError {
  border-width: 3px;
}
複製代碼

控制指令

@if

和 JavaScript 的 if 同樣:

$type: monster;
p {
  @if $type == ocean {
    color: blue;
  } @else if $type == monster {
    color: green;
  } @else {
    color: black;
  }
}
複製代碼
p {
  color: green;
}
複製代碼

@for

區別在於 through 與 to 的含義:through 包含最後一位,而 to 不包含:

@for $i from 1 to 3 {
  .list-#{$i} {
    width: 1em * $i;
  }
}
@for $i from 1 through 3 {
  .item-#{$i} {
    width: 2rem * $i;
  }
}
複製代碼
.list-1 {
  width: 1em;
}

.list-2 {
  width: 2em;
}

.item-1 {
  width: 2rem;
}

.item-2 {
  width: 4rem;
}

.item-3 {
  width: 6rem;
}
複製代碼

@each

相似於 JavaScript 的 for...in

@each $kind in small, middle, large {
  .#{$kind}-icon {
    background-image: url("/images/#{$kind}-icon.png");
  }
}
複製代碼
.small-icon {
  background-image: url("/images/small-icon.png");
}

.middle-icon {
  background-image: url("/images/middle-icon.png");
}

.large-icon {
  background-image: url("/images/large-icon.png");
}
複製代碼

混合器

混合器使用@mixin標識符定義,經過@include來使用這個混合器,用來解決大段重用的代碼。

@mixin clearfix {
  display: inline-block;
  &:after {
    content: ".";
    display: block;
    height: 0;
    clear: both;
    visibility: hidden;
  }
  * html & {
    height: 1px;
  }
}

.clearfix {
  @include clearfix;
}
複製代碼
.clearfix {
  display: inline-block;
}

.clearfix:after {
  content: ".";
  display: block;
  height: 0;
  clear: both;
  visibility: hidden;
}

* html .clearfix {
  height: 1px;
}
複製代碼

最強大的一點就是如同函數通常,能夠傳參,不只能夠指定默認值,而且可使用關鍵詞參數,這樣就不用管參數先後順序了:

@mixin border-value($width: 1px, $color: #333, $style: solid) {
  border-width: $width;
  border-color: $color;
  border-style: $style;
}
/*不傳參*/
h1 {
  @include border-value;
}
/*傳參*/
h2 {
  @include border-value(2px, #666, dashed);
}
/*關鍵詞傳參*/
h3 {
  @include border-value($style: dashed, $width: 3px, $color: #999);
}
複製代碼
/*不傳參*/
h1 {
  border-width: 1px;
  border-color: #333;
  border-style: solid;
}

/*傳參*/
h2 {
  border-width: 2px;
  border-color: #666;
  border-style: dashed;
}

/*關鍵詞傳參*/
h3 {
  border-width: 3px;
  border-color: #999;
  border-style: dashed;
}
複製代碼

函數指令

與 mixin 相同,也能夠傳遞若干個全局變量給函數做爲參數。一個函數能夠含有多條語句,須要調用 @return 輸出結果。

$grid-width: 40px;
$gutter-width: 10px;

@function grid-width($n) {
  @return $n * $grid-width + ($n - 1) * $gutter-width;
}

.sidebar1 {
  width: grid-width(5);
}
.sidebar2 {
  width: grid-width($n: 10);
}
複製代碼
.sidebar1 {
  width: 240px;
}

.sidebar2 {
  width: 490px;
}
複製代碼

SassScript

數據類型

SassScript 支持 6 種主要的數據類型:

  • 數字,1, 2, 13, 10px
  • 字符串,有引號字符串與無引號字符串,"foo", 'bar', baz
  • 顏色,blue, #04a3f9, rgba(255,0,0,0.5)
  • 布爾型,true, false
  • 空值,null
  • 數組 (list),用空格或逗號做分隔符,1.5em 1em 0 2em, Helvetica, Arial, sans-serif
  • maps, 至關於 JavaScript 的 object,(key1: value1, key2: value2)

運算

SassScript 支持數字的加減乘除、取整等運算 (+, -, *, /, %),關係運算 <, >, <=, >= 也可用於數字運算,相等運算 ==, != 可用於全部數據類型。

插值語句 #{}

經過 #{} 插值語句能夠在選擇器或屬性名中使用變量,避免 Sass 運行運算表達式。

Bootstrap@4

入口文件 bootstrap.scss的引入組件不少,咱們就挑一個看看,好比下面是咱們最終的 float 內容:

.float-left {
  float: left !important;
}

.float-right {
  float: right !important;
}

.float-none {
  float: none !important;
}

@media (min-width: 576px) {
  .float-sm-left {
    float: left !important;
  }
  .float-sm-right {
    float: right !important;
  }
  .float-sm-none {
    float: none !important;
  }
}

@media (min-width: 768px) {
  .float-md-left {
    float: left !important;
  }
  .float-md-right {
    float: right !important;
  }
  .float-md-none {
    float: none !important;
  }
}

@media (min-width: 992px) {
  .float-lg-left {
    float: left !important;
  }
  .float-lg-right {
    float: right !important;
  }
  .float-lg-none {
    float: none !important;
  }
}

@media (min-width: 1200px) {
  .float-xl-left {
    float: left !important;
  }
  .float-xl-right {
    float: right !important;
  }
  .float-xl-none {
    float: none !important;
  }
}
複製代碼

而後,咱們去看看 bootstrap 是如何實現的:

第一步:找路

根據 bootstrap.scss裏的內容@import "mixins";,進入當前目錄下的_mixins.scss,看到@import "mixins/float";,因此繼續打開mixins 目錄下的 _float.scss

第二步:內容

_float.scss全部內容以下:

// stylelint-disable declaration-no-important

@each $breakpoint in map-keys($grid-breakpoints) {
  @include media-breakpoint-up($breakpoint) {
    $infix: breakpoint-infix($breakpoint, $grid-breakpoints);

    .float#{$infix}-left {
      float: left !important;
    }
    .float#{$infix}-right {
      float: right !important;
    }
    .float#{$infix}-none {
      float: none !important;
    }
  }
}
複製代碼

接着,有三個地方,我不知道是什麼,如map-keys()media-breakpoint-up()breakpoint-infix()

第三步:解惑

  • map-keys() 返回 map 裏面全部的 key:
$grid-breakpoints: (
  xs: 0,
  sm: 576px,
  md: 768px,
  lg: 992px,
  xl: 1200px
) !default;

@each $breakpoint in map-keys($grid-breakpoints) {
  .#{$breakpoint} {
    color: red;
  }
}

// css
.xs {
  color: red;
}

.sm {
  color: red;
}

.md {
  color: red;
}

.lg {
  color: red;
}

.xl {
  color: red;
}
複製代碼

資料:Sass map 詳解

  • media-breakpoint-up(),自定義函數,主要是根據媒體查詢給出不一樣的結果
// Media of at least the minimum breakpoint width. No query for the smallest breakpoint.
// Makes the @content apply to the given breakpoint and wider.
@mixin media-breakpoint-up($name, $breakpoints: $grid-breakpoints) {
  $min: breakpoint-min($name, $breakpoints);
  @if $min {
    @media (min-width: $min) {
      @content;
    }
  } @else {
    @content;
  }
}
複製代碼

這裏breakpoint-min()也是個函數:

// Minimum breakpoint width. Null for the smallest (first) breakpoint.
//
// >> breakpoint-min(sm, (xs: 0, sm: 576px, md: 768px, lg: 992px, xl: 1200px))
// 576px
@function breakpoint-min($name, $breakpoints: $grid-breakpoints) {
  $min: map-get($breakpoints, $name);
  @return if($min != 0, $min, null);
}
複製代碼

這裏的map-getmap-keys用法,返回 map 裏面指定能夠的 value

$min-num: breakpoint-min(sm, $grid-breakpoints);

@media (min-width: $min-num) {
  p {
    color: #444;
  }
}

// css
@media (min-width: 576px) {
  p {
    color: #444;
  }
}
複製代碼

@content用在mixin裏面的,當定義一個mixin後,而且設置了@content以後,、@include的時候能夠傳入相應的內容到mixin裏面:

$color: white;
@mixin colors($color: blue) {
  background-color: $color;
  @content;
  border-color: $color;
}
.colors {
  @include colors {
    color: $color;
  }
}

// css
.colors {
  background-color: blue;
  color: white;
  border-color: blue;
}
複製代碼

資料:sass 語法中的@content

  • breakpoint-infix(),自定義函數:
// Returns a blank string if smallest breakpoint, otherwise returns the name with a dash in front.
// Useful for making responsive utilities.
//
// >> breakpoint-infix(xs, (xs: 0, sm: 576px, md: 768px, lg: 992px, xl: 1200px))
// "" (Returns a blank string)
// >> breakpoint-infix(sm, (xs: 0, sm: 576px, md: 768px, lg: 992px, xl: 1200px))
// "-sm"
@function breakpoint-infix($name, $breakpoints: $grid-breakpoints) {
  @return if(breakpoint-min($name, $breakpoints) == null, "", "-#{$name}");
}
複製代碼

根據註釋咱們演示一下:

$min-value-sm: breakpoint-infix(sm, $grid-breakpoints);
$min-value-xs: breakpoint-infix(xs, $grid-breakpoints);

.float#{$min-value-sm}-left {
  float: left;
}
.float#{$min-value-xs}-left {
  float: left;
}

// css
.float-sm-left {
  float: left;
}

.float-left {
  float: left;
}
複製代碼

整合

最後,咱們把全部關於 float 的內容組合在一塊兒:

$grid-breakpoints: (
  xs: 0,
  sm: 576px,
  md: 768px,
  lg: 992px,
  xl: 1200px
) !default;

@function breakpoint-min($name, $breakpoints: $grid-breakpoints) {
  $min: map-get($breakpoints, $name);
  @return if($min != 0, $min, null);
}

@function breakpoint-infix($name, $breakpoints: $grid-breakpoints) {
  @return if(breakpoint-min($name, $breakpoints) == null, "", "-#{$name}");
}

@mixin media-breakpoint-up($name, $breakpoints: $grid-breakpoints) {
  $min: breakpoint-min($name, $breakpoints);
  @if $min {
    @media (min-width: $min) {
      @content;
    }
  } @else {
    @content;
  }
}

@each $breakpoint in map-keys($grid-breakpoints) {
  @include media-breakpoint-up($breakpoint) {
    $infix: breakpoint-infix($breakpoint, $grid-breakpoints);

    .float#{$infix}-left {
      float: left !important;
    }
    .float#{$infix}-right {
      float: right !important;
    }
    .float#{$infix}-none {
      float: none !important;
    }
  }
}
複製代碼

這樣直接就能夠在環境裏跑起來了。

相關文章
相關標籤/搜索