切換頁面主題樣式研究及less教程

gentlecoder發表於2019-04-14

某一天,一個頭條的大佬問我,聽說你之前在專案裡面弄過主題切換,你當時是怎麼實現的可以詳說一下嗎?

如果已經對less瞭如指掌,直接從這裡開始

從less說起

使用

Node.js 環境中使用 Less :

npm install -g less
> lessc styles.less styles.css
複製程式碼

在瀏覽器環境中使用 Less :

<link rel="stylesheet/less" type="text/css" href="styles.less" />
<script src="//cdnjs.cloudflare.com/ajax/libs/less.js/3.8.1/less.min.js" ></script>
複製程式碼

不過比較推薦的還是通過webpack或者gulp等工具先將less編譯成css,然後再引入使用。

變數

@nice-blue: #5B83AD;
@light-blue: @nice-blue + #111;

#header {
  color: @light-blue;
}
複製程式碼

混合

  • 常用

    .bordered {
      border-top: dotted 1px black;
      &:hover {
        border: 1px solid red;
      }  // 同樣可以包含選擇器混用
    }
    .post a {
      color: red;
      .bordered !important;  // 可以在屬性後面都加上!important
    }
    複製程式碼
  • 編譯後不輸出至css檔案

    .my-other-mixin() {
      background: white;
    }
    複製程式碼
  • 作用域混合

    #outer {
      .inner() {
        color: red;
      }
    }
    #outer1 {
      .inner() {
        color: blue;
      }
    }
    .c {
      #outer > .inner;
    }
    複製程式碼

    輸出

    .c {
      color: red;
    }
    複製程式碼
  • 擁有前置條件的作用域混合,更多詳情

    @mode: little;
    #outer when (@mode=huge) {
      .inner {
        color: red;
      }
    }
    #outer when (@mode=little) {
      .inner {
        color: blue;
      }
    }
    .c {
      #outer > .inner;
    }
    複製程式碼

    輸出(可以看到沒有通過前置條件的樣式被過濾了)

    #outer .inner {
      color: blue;
    }
    .c {
      color: blue;
    }
    複製程式碼
  • 帶引數混合,可以指定預設值,可以帶多個引數,使用時可以通過名稱賦值

    .mixin(@color: black; @margin: 10px; @padding: 20px) {
      color: @color;
      margin: @margin;
      padding: @padding;
    }
    .class1 {
      .mixin(@margin: 20px; @color: #33acfe);
    }
    .class2 {
      .mixin(#efca44; @padding: 40px);
    }
    複製程式碼
  • 使用@arguments

    .mixin(@a; @b) {
      margin: @arguments; 
      right:extract(@arguments,2); 
      top:@b;
    }
    p {.mixin(1px; 2px);}
    複製程式碼

    輸出

    p {
      margin: 1px 2px;
      right: 2px;
      top: 2px;
    }
    複製程式碼
  • 使用@rest引數

    // 方式1
    .mixin(@listofvariables...) {
      border: @listofvariables;
    }
    p {
      .mixin(1px; solid; red);
    }
    // 方式2
    .mixin(@a; ...) { color: @a;}
    .mixin(@a) { background-color: contrast(@a); width:100%;}
    .mixin(@a; @b;) { background-color: contrast(@a); width:@b;}
    p {
    .mixin(red);
    }
    p.small {
    .mixin(red,50%);
    }
    複製程式碼

    輸出

    /*方式1*/
    p {
      border: 1px solid red;
    }
    /*方式2*/
    p {
      color: red;
      background-color: #ffffff;
      width: 100%;
    }
    p.small {
      color: red;
      background-color: #ffffff;
      width: 50%;
    }
    複製程式碼
  • 模式匹配混合

    .mixin(dark; @color) {
      color: darken(@color, 10%);
    }
    .mixin(light; @color) {
      color: lighten(@color, 10%);
    }
    .mixin(@_; @color) {
      display: block;
    }
    @switch: light;
    .class {
      .mixin(@switch; #888);
    }
    複製程式碼

    輸出

    .class {
      color: #a2a2a2;
      display: block;
    }
    複製程式碼
  • 規則集混合

    // declare detached ruleset
    @detached-ruleset: { background: red; };
    
    // use detached ruleset
    .top {
        @detached-ruleset(); 
    }
    複製程式碼

函式

類似於先函式運算計算出變數的值,再通過變數的值設定屬性。

.mixin() {
  @width:  100%;
  @height: 200px;
}

.caller {
  .mixin();
  width:  @width;
  height: @height;
}
複製程式碼

輸出

.caller {
  width:  100%;
  height: 200px;
}
複製程式碼

繼承

繼承另外一個選擇器的屬性,更多詳情

nav ul {
  &:extend(.inline);
  background: blue;
}  // &是父型別選擇器,指代的是nav ul
.inline {
  color: red;
}
複製程式碼

輸出

nav ul {
  background: blue;
}
.inline,
nav ul {
  color: red;
}
複製程式碼

巢狀

#header {
  color: black;
  .navigation {
    font-size: 12px;
  }
  .logo {
    width: 300px;
  }
}
複製程式碼

引入

@import "foo";      // foo.less is imported
@import "foo.less"; // foo.less is imported
@import "foo.php";  // foo.php imported as a less file
@import "foo.css";  // statement left in place, as-is
複製程式碼

引數

@import (keyword) "filename";

  • reference: use a Less file but do not output it
  • inline: include the source file in the output but do not process it
  • less: treat the file as a Less file, no matter what the file extension
  • css: treat the file as a CSS file, no matter what the file extension
  • once: only include the file once (this is default behavior)
  • multiple: include the file multiple times
  • optional: continue compiling when file is not found

迴圈

.generate-columns(4);

.generate-columns(@n, @i: 1) when (@i =< @n) {
  .column-@{i} {
    width: (@i * 100% / @n);
  }
  .generate-columns(@n, (@i + 1));
}
複製程式碼

輸出

.column-1 {
  width: 25%;
}
.column-2 {
  width: 50%;
}
.column-3 {
  width: 75%;
}
.column-4 {
  width: 100%;
}
複製程式碼

合併

  • 逗號合併

    .mixin() {
      box-shadow+: inset 0 0 10px #555;
    }
    .myclass {
      .mixin();
      box-shadow+: 0 0 20px black;
    }
    複製程式碼

    輸出

    .myclass {
      box-shadow: inset 0 0 10px #555, 0 0 20px black;
    }
    複製程式碼
  • 空格合併

    .mixin() {
      transform+_: scale(2);
    }
    .myclass {
      .mixin();
      transform+_: rotate(15deg);
    }
    複製程式碼

    輸出

    .myclass {
      transform: scale(2) rotate(15deg);
    }
    複製程式碼

切換主題樣式

方案1

當幾種主題佈局類似,幾乎只是顏色不同時,可以使用這種。

通過對less的瞭解(可以進行許多額外的騷操作哦),我們這裡最簡單地編寫出如下less檔案。

  • 基礎樣式模版style.less,裡面主要通過變數設定各個樣式
  • 愛國紅樣式patriotic-red.less,設定變數的值
  • 天空藍樣式sky-blue.less,設定不同的變數值
  • ...

style.less裡樣式類似這樣

a,
.link {
  color: @link-color;
}
a:hover {
  color: @link-color-hover;
}
.widget {
  color: #fff;
  background: @link-color;
}
複製程式碼

patriotic-red.less裡樣式類似這樣

@import "style";
@link-color: #f03818; 
@link-color-hover: darken(@link-color, 10%);
複製程式碼

sky-blue.less裡樣式類似這樣

@import "test";
@link-color: #428bca;
@link-color-hover: darken(@link-color, 10%);
複製程式碼

利用相關工具(或原始人手動lessc)提前編譯成patriotic-red.csssky-blue.css檔案。

這裡簡單的假設頁面header中只引入了預設愛國紅——

<link rel="stylesheet" href="./patriotic-red.css" />

同時存在一個按鈕,使用者點選時切換主題。首先我們給按鈕繫結點選事件,當使用者點選時刪除當前匯入的樣式,然後再引入另外一個樣式。具體操作如下:

  function toggleThemeClick() {
    let a = document.getElementsByTagName("link");
    let aHref = a[0].getAttribute("href").slice(2, -4);
    a[0].parentElement.removeChild(a[0]);
    let b = document.createElement("link");
    b.setAttribute("rel", "stylesheet");
    if ("patriotic-red" === aHref) {
      b.setAttribute("href", "./sky-blue.css");
    } else {
      b.setAttribute("href", "./patriotic-red.css");
    }
    document.getElementsByTagName("head")[0].appendChild(b);
  }
複製程式碼

這樣我們就可以自由的切換主題啦。

方案2

我們還可以通過給body新增類標籤來進行主題的切換。

新建一個style-mixin.less,裡面內容如下——

.patriotic-red {
  @import "patriotic-red";
}
.sky-blue {
  @import "sky-blue";
}
複製程式碼

這裡需要注意的是,在sky-blue.less或者patriotic-red.less中引入style.less時,需要使用(multiple)引數,否則會只編譯出一份樣式。編譯出來的樣式會自動加上.patriotic-redsky-blue字首。

這個時候只需要引入一份style-mixin.css就行了,要切換樣式的時候修改body的類標籤。

document,getElementsByTagName('body')[0].className='xxx'

題外話

頭條大佬似乎並不是很認可方案1,他認為方案1會導致之前引入的樣式和後來的衝突?我沒有明白具體是什麼意思,由於時間關係他也沒有解釋得很清楚,希望知道問題出在哪裡的同學告訴我一下哦。

ps,有沒有更好的切換主題的方案呢,求大佬指點~

參考

lesscss.cn

相關文章