如何編寫一個按鈕樣式系統

最近計劃開源一個框架,這裏把其中一部分拿出來作個引子。看一下咱們如何完成一個按鈕的製做。如下代碼用SCSS編寫 咱們先來作一個簡單的。css

簡單的上手

.btn{
    display: inline-block;
    font-weight: 400;
    text-align: center;
    vertical-align: middle;
    white-space: nowrap;
    line-height:26px;
}
複製代碼

增長瀏覽器支持

夠簡單吧,下面咱們逐步豐富一下html

.btn{
    //上面寫過的代碼就省略了
    touch-action: manipulation;//解決移動端延遲問題
    cursor: pointer;//修改PC端鼠標樣式
    white-space: nowrap;//對文字進行一下處理
}
複製代碼
<div class="btn">這是個案例</div>
複製代碼
這是個案例

禁用選擇

若是用戶出現了滑動選擇的操做行爲,瀏覽器的默認樣式會看起來很難看,因此禁用一下選擇web

.btn{
    //上面寫過的代碼就省略了
    -webkit-user-select: none;
       -moz-user-select: none;
        -ms-user-select: none;
            user-select: none;
}
複製代碼

案例展現bootstrap

<div class="btn">這裏是不能選擇的</div>
複製代碼
這裏是不能選擇的

進行封裝

這個看起來不是特別友好因此封裝起來,總體以下瀏覽器

@mixin user-select($select) {
  -webkit-user-select: $select;
     -moz-user-select: $select;
      -ms-user-select: $select;
          user-select: $select;
}
.btn{
    display: inline-block;
    font-weight: 400;
    text-align: center;
    vertical-align: middle;
    white-space: nowrap;
    line-height:26px;
    touch-action: manipulation;//解決移動端延遲問題
    cursor: pointer;//修改PC端鼠標樣式
    white-space: nowrap;//對文字進行一下處理
    @include user-select(none);
}
複製代碼

色彩系統與樣式組合

如今咱們給按鈕上色,說到顏色,這個問題就比較難講,從bootstrap開始,按鈕的命名彷佛就是一成不變的,全部的綠色都叫success,全部的紅色都加error,這種現象已經持續了將近十年,幾乎全部的UI框架都是這麼作的。可是實際上存在一個問題,就是業務和展現融合在了一塊兒,好比我須要作一個加入購物車的按鈕,爲何我要命名爲btn-error呢?或者有一天UI要將這個按鈕的顏色從紅色變成綠色,你又該如何操做呢。微信

在個人思惟邏輯裏,最但願看到的就是所想即所寫,所寫即所得。也就是說,當我看到設計稿的上繪製的是紅色,我寫的就應該是紅色,網頁顯示的也應該是紅色,一樣的邏輯咱們能夠採用徹底脫離業務的命名系統,經過class的組合來拓展樣式,所以咱們須要創建一個色彩系統,這裏以赤橙黃綠青藍紫來舉例;框架

$bg_colorList:(
	'red': #ff4c48,
	'orange': #ff9800,
	'yellow': #ff6705,
	'green': #2eb252,
	'coffee': #853f3a,
	'blue': #25aaff,
	'purple': #7000C8,
	'black':#000000,
	'white':#ffffff
);
.btn{
    //上面寫過的代碼就省略了
    color: white;//設置文字顏色
}
@each $colorName,$colorValue in $bg_colorList{
  .btn.#{$colorName}{
    background-color: $colorValue;
  }
}
複製代碼

案例展現flex

<div class="btn red"></div>
複製代碼
this is a btn

樣式翻轉

在咱們使用的按鈕中並非全部的都是實心白字的,不少時候會用到彩色的邊框,彩色的字的按鈕,所以咱們給按鈕一個翻轉的樣式優化

@each $colorName,$colorValue in $bg_colorList{
  .btn.#{$colorName}{
    background-color: $colorValue;
    &.reverse{
        background-color: white;
        border:1px solid $colorValue;
        color:$colorValue;
    }
  }
}
複製代碼

案例展現this

<div class="btn red reverse"></div>
複製代碼
this is a btn

邊框調整

如今問題出現了,翻轉的按鈕多了一像素的邊框,高度增長了兩個像素(看下面的案例),爲了保證全部按鈕的尺寸統一,咱們能夠採用兩種方式,給實心按鈕增長和背景色相同的邊框,或者修改實心按鈕的高度,這裏咱們採用第一種方式。

this is a btn
this is a btn

這裏另個btn高度明顯看到差一個像素

@each $colorName,$colorValue in $bg_colorList{
  .btn.#{$colorName}{
    background-color: $colorValue;
    border:1px solid $colorValue;//增長邊框
    &.reverse{
        background-color: white;
        border:1px solid $colorValue;
        color:$colorValue;
    }
  }
}
複製代碼

案例展現

<div class="btn red"></div>
<div class="btn red reverse"></div>
複製代碼
this is a btn
reverse btn

調整後的效果

樣式抽取合併

你會發現這裏有不少樣式是重複的,因此咱們能夠進行樣式抽取

@mixin button-variant($color, $background, $border) {
  color: $color;
  background-color: $background;
  border-color: $border;
}
.btn{
    border: 1px solid transparent;
    @include button-variant(#666, #eee, #ccc);//設置默認色一般不會用到
    &.reverse{
        @include button-variant(#666, white, #ccc);
    }
}
@each $colorName,$colorValue in $bg_colorList{
  .btn.#{$colorName}{
    @include button-variant(white, $colorValue, $colorValue);
    &.reverse{
      @include button-variant(map-get($colorList,#{$colorName}), white, $colorValue);
    }
  }
}
複製代碼

disable

接下來增長對disable和active的處理(這裏只寫出移動端的樣式,PC端會稍複雜一些)

@mixin button-variant($color, $background, $border) {
  color: $color;
  background-color: $background;
  border-color: $border;
}
.btn{
    &.disabled,
    &[disabled],
    fieldset[disabled] & {
        cursor: not-allowed;
        opacity:.55;
        box-shadow:none
    }
}
a.btn {//a標籤須要的額外處理
  &.disabled,
  fieldset[disabled] & {
    pointer-events: none; 
  }
}
複製代碼
<div class="btn red disable"></div>
<div class="btn red reverse disable"></div>
複製代碼
red disable
reverse and disable

效果展現

設置padding

接下來咱們設置pading並調整一下按鈕的高度,若是咱們想作一個高度爲36的按鈕,行高26 邊框1像素,那麼上下的padding就應該是(36-26-2)/2 結果爲4;水平方向沒有影響,至於爲何會選擇44 36 28 而不選擇其餘的數值做爲默認值,不在咱們本次的討論範圍內,之後會講到。

.btn{
    padding:4px 15px;
}
複製代碼

按鈕固然不能只有一個尺寸,咱們能夠多設計幾個,並把相關代碼提取出來。

$btn-size-list:(//$height, $padding-horizontal, $font-size
	'base':(36px,15px,16px),
	'small':(28px,15px,14px),
	'big':(44px,15px,16px),
);
@mixin button-size($height, $padding-horizontal, $font-size) {
  padding: ($height - 26px - 2) / 2 $padding-horizontal;
  font-size: $font-size;
}
.btn{
    @include button-size(
        nth(map-get($btn-size-list,'base'),1),
        nth(map-get($btn-size-list,'base'),2),
        nth(map-get($btn-size-list,'base'),3)
    );
}
@each $btnSizeName,$btnSizeValue in $btn-size-list{
  @if(#{$btnSizeName}!='base'){
    .btn.#{$btnSizeName}{
      @include button-size(
          nth($btnSizeValue,1),
          nth($btnSizeValue,2),
          nth($btnSizeValue,3)
      );
    }
  }
}
複製代碼
<div class="btn red small"></div>
<div class="btn red "></div>
<div class="btn red big "></div>
複製代碼
small
default
big

效果展現

圓角處理

$border-radius-base:        4px !default;
.btn{
    &.radius{
        border-radius: $border-radius-base;
      }
}
複製代碼
<div class="btn red radius"></div>
<div class="btn red reverse radius"></div>
複製代碼
default
reverse

效果展現

分組支持

在一些表單展現中會出現練成一排的按鈕,若是帶有圓角的話一般只有第一個和最後一個帶有圓角。所以咱們增長一下分組的支持;

.btn-group{
  padding-left:1px;//抵消按鈕負邊距的距離
  @include clearfix();//清除浮動
  .btn{
    position: relative;//修改定位
    float: left;
    margin-left:-1px;//設置負邊距讓兩個翻轉按鈕連在一塊兒的時候邊框只有一像素
    &.radius{
      border-radius:0;
      &:first-child{
        border-radius: $border-radius-base 0 0 $border-radius-base;
      }
      &:last-child{
        border-radius: 0 $border-radius-base  $border-radius-base 0;
      }
    }
  }
}
複製代碼
<div class="btn-group">
    <div class="btn red reverse radius"></div>
    <div class="btn red reverse radius"></div>
    <div class="btn red reverse radius"></div>
</div>

複製代碼
reverse
reverse
reverse

效果展現

塊級支持

接下來咱們再給按鈕增長一個鋪滿一行的狀態,這個一般是用於展現一個比較長的按鈕,好比登錄註冊,加入購物車,當即購買等。

.btn.block {
  display: block;
}
.btn.block + .btn.block{
  margin-top: 5px;
}
input[type="submit"],
input[type="reset"],
input[type="button"] {
  &.btn.block {
    width: 100%;
  }
}
複製代碼
<div class="btn red block"></div>
複製代碼
寬度佔據整個容器的btn

效果展現

完整結構

至此一個按鈕就基本完成了,咱們來看一下完整代碼;

$border-radius-base:4px;
$btn-size-list:(//$height, $padding-horizontal, $font-size
	'base':(36px,15px,16px),
	'small':(28px,15px,14px),
	'big':(44px,15px,16px),
);
$bg_colorList:(
	'red': #ff4c48,
	'orange': #ff9800,
	'yellow': #ff6705,
	'green': #2eb252,
	'coffee': #853f3a,
	'blue': #25aaff,
	'purple': #7000C8,
	'black':#000000,
	'white':#ffffff
);
@mixin clearfix() {
  &:before,
  &:after {
    content: " ";
    display: table;
  }
  &:after {
    clear: both;
  }
}
@mixin user-select($select) {
  -webkit-user-select: $select;
     -moz-user-select: $select;
      -ms-user-select: $select;
          user-select: $select;
}
@mixin button-variant($color, $background, $border) {
  color: $color;
  background-color: $background;
  border-color: $border;
}
@mixin button-size($height, $padding-horizontal, $font-size) {
  padding: ($height - 26px - 2) / 2 $padding-horizontal;
  font-size: $font-size;
}
.btn {
  display: inline-block;
  margin-bottom: 0; 
  font-weight: 400;
  text-align: center;
  vertical-align: middle;
  touch-action: manipulation;
  cursor: pointer;
  background-image: none; 
  border: 1px solid transparent;
  white-space: nowrap;
  line-height:26px;
  @include button-variant(#666, #eee, #ccc);
  @include button-size(
      nth(map-get($btn-size-list,'base'),1)
      ,nth(map-get($btn-size-list,'base'),2)
      ,nth(map-get($btn-size-list,'base'),3)
  );
  @include user-select(none);
  &.radius{
    border-radius: $border-radius-base;
  }
  &.reverse{
    @include button-variant(#666, white, #ccc);
  }
  &.disabled,
  &[disabled],
  fieldset[disabled] & {
    cursor: not-allowed;
    opacity:.55;
    box-shadow:none
  }
}
@each $btnSizeName,$btnSizeValue in $btn-size-list{
  @if(#{$btnSizeName}!='base'){
    .btn.#{$btnSizeName}{
      @include button-size(
          nth($btnSizeValue,1),
          nth($btnSizeValue,2),
          nth($btnSizeValue,3)
      );
    }
  }
}
a.btn {
  &.disabled,
  fieldset[disabled] & {
    pointer-events: none; 
  }
}
@each $colorName,$colorValue in $bg_colorList{
  .btn.#{$colorName}{
    @include button-variant(white, $colorValue, $colorValue);
    &.reverse{
      @include button-variant($colorValue, white, $colorValue);
    }
  }
}
.btn.block {
  display: block;
}
.btn.block + .btn.block{
  margin-top: 5px;
}
input[type="submit"],
input[type="reset"],
input[type="button"] {
  &.btn.block {
    width: 100%;
  }
}
//btn-group
.btn-group{
  padding-left:1px;
  @include clearfix();
  .btn{
    position: relative;
    float: left;
    margin-left:-1px;
    &.radius{
      border-radius:0;
      &:first-child{
        border-radius: $border-radius-base 0 0 $border-radius-base;
      }
      &:last-child{
        border-radius: 0 $border-radius-base  $border-radius-base 0;
      }
    }
  }
}
複製代碼
<div class="btn red radius"></div>
<div class="btn red reverse radius"></div>
複製代碼
default
red
orange
yellow
green
coffee
blue
purple

效果展現

操做舉例

如今咱們已經能夠經過組合的方式來展現各類各樣的按鈕了,你可使用任何你須要使用的標籤,這裏均已DIV舉例

<div class="btn">默認</div>
<div class="btn red">紅色按鈕</div><!--也能夠將red替換成blue green等-->
<div class="btn small red">紅色小按鈕</div><!--也能夠將替換成big-->
<div class="btn small red radius">紅色圓角小按鈕</div>
<div class="btn small red radius reverse">紅色翻轉圓角小按鈕</div>
<div class="btn small red radius reverse block">寬紅色翻轉圓角小按鈕</div>
<div class="btn-group">
    <div class="btn small red radius">第一個</div>
    <div class="btn small red radius">第二個</div>
    <div class="btn small red radius">第三個</div>
</div>
複製代碼

後續優化

前文展現的代碼只是按鈕系統的一部分,實際的代碼要比這個複雜的多,包括以下一些沒有講到的內容

  • 按鈕和標籤以及圖標的組合
  • PC端不一樣狀態的切換
  • 表單的組合使用
  • 不一樣色彩濃度的調整
  • 按需加載:動態生成和加載色彩系統
  • 動態修改:兩個頁面都使用了紅色按鈕但要求顏色不一樣
  • 對方形 藥片形 圓形等樣式的支持

可是如今的已經能夠直接編譯使用,若是須要設置其餘的尺寸或顏色能夠修改默認的配置,編譯生成直接使用就能夠了。

若是你以爲還有什麼功能是你須要可是在這裏沒提到的能夠添加個人微信給我留言,更多文章及直播教程能夠關注冰山工做室公衆號

相關文章
相關標籤/搜索