1.0 HTML/CSS 優化--《高效前端》學習筆記

Github 地址 (可查看交互效果)css

切圖的三個境界:html

  • 長得好看
  • 靈活
  • 友好的交互

高效前端1:能用-html-css-解決的問題就不要用-js

導航高亮

給不一樣頁面添加不一樣類,標識不一樣頁面,而後設置當前頁面樣式,覆蓋掉默認樣式。前端

代碼:css3

<div class="demo1">
  <ul class="nav">
    <li class="nav-item item-home">首頁</li>
    <li class="nav-item item-demo1">導航高亮</li>
  </ul>
</div>
.nav {
  padding: 5px 10px;
  background: #000;
  color: #fff;
}
.nav .nav-item {
  display: inline-block;
  margin-right: 10px;
  list-style: none;
  opacity: 0.5;
  cursor: pointer;
  &:hover {
    opacity: 1;
  }
}
.demo1 .nav.nav-item.item-demo1 {
  opacity: 1;
}

本身的想法:這種方式雖然好,可是,須要爲每一個導航都寫一個默認和高亮樣式,若是不是同一我的寫的代碼,在新增導航的時候,很容易會忘記去加上。git

看到後面的時候,發現書中有這個問題相關的回答,能夠用 sass 進行 for 循環實現。同時,還能夠定義主題色變量。github

鼠標懸浮時顯示

hover 到某個菜單時,顯示子菜單。sass

代碼:less

<!-- html -->
<div class="demo2">
  <ul class="nav">
    <li class="nav-item item-home">首頁</li>
    <li class="nav-item item-demo1">導航高亮</li>
    <li class="menu">
      <ul>
        <li>導航高亮-下級1</li>
        <li>導航高亮-下級2</li>
      </ul>
    </li>
    <li class="nav-item item-demo2">導航懸浮顯示下級</li>
    <li class="menu">
      <ul>
        <li>導航懸浮顯示下級-下級1</li>
        <li>導航懸浮顯示下級-下級2</li>
      </ul>
    </li>
  </ul>
</div>
// less
.nav {
  position: relative;
  padding: 5px 10px;
  background: #06a992;
  color: #fff;
}
.nav .nav-item {
  display: inline-block;
  margin-right: 10px;
  list-style: none;
  opacity: 0.5;
  cursor: pointer;
  &:hover { // <-- 在導航菜單上須要加 hover
    opacity: 1;
  }
}
.demo2 .nav .nav-item.item-demo2 {
  opacity: 1;
}
.nav-item:hover + .menu{
  display: list-item;
}
.menu {
  display: none;
  position: absolute;
  top: 44px;
  min-width: 100px;
  color: #000;
  border: 1px solid #000;
  box-shadow: 0 0 5px;
  &:before { // <-- 加一個僞元素,能夠避免當下拉列表和導航菜單名稱之間有空隙時,鼠標往下移到下拉列表的過程當中,脫離導航菜單名稱而隱藏下拉列表的狀況
    content: "";
    position: absolute;
    left: 0;
    top: -20px;
    width: 100%;
    height: 20px;
  }
  &:hover { // <-- 隱藏元素自己也須要加 hover
    display: list-item;
  }
}
ul, ul li {
  list-style: none;
}

本身的想法:書中提到,能夠經過 absolute 給 .menu 定位,我想了很久,都想不出來怎麼實現,若是有實現方法的,請告知,謝謝!佈局

 

對上面的 demo 作了佈局的改變,如今能夠簡單的經過 absolute 來定位了,參考:flex

代碼:

<!-- html -->
<div class="demo2">
  <nav>
    <ul class="nav-ul">
      <li class="nav-item item-home">首頁</li>
    </ul>
    <ul class="nav-ul">
      <li class="nav-item item-demo1">導航高亮</li>
      <li class="menu">
        <ul class="menu-ul">
          <li>導航高亮-下級1</li>
          <li>導航高亮-下級2</li>
        </ul>
      </li>
    </ul>
    <ul class="nav-ul">
      <li class="nav-item item-demo2">導航懸浮顯示下級</li>
      <li class="menu">
        <ul class="menu-ul">
          <li>導航懸浮顯示下級-下級1</li>
          <li>導航懸浮顯示下級-下級2</li>
        </ul>
      </li>
    </ul>
  </nav>
</div>
// less
nav {
  font-size: 0;
}
.nav-ul {
  display: inline-block;
  position: relative;
  padding: 5px 10px;
  font-size: 16px;
  background: #06a992;
  color: #fff;
}
.nav-ul .nav-item {
  display: inline-block;
  margin-right: 10px;
  list-style: none;
  opacity: 0.5;
  cursor: pointer;
  &:hover {
    opacity: 1;
  }
}
.demo2 .nav-ul .nav-item.item-demo2 {
  opacity: 1;
}

.nav-item:hover + .menu{
  display: list-item;
}

.menu {
  display: none;
  position: absolute;
  top: 44px;
  min-width: 100px;
  white-space: nowrap;
  color: #000;
  border: 1px solid #000;
  box-shadow: 0 0 5px;
  &:before { // <-- 加一個僞元素,能夠避免當下拉列表和導航菜單名稱之間有空隙時,鼠標往下移到下拉列表的過程當中,脫離導航菜單名稱而隱藏下拉列表的狀況
    content: "";
    position: absolute;
    left: 0;
    top: -20px;
    width: 100%;
    height: 20px;
  }
  &:hover {
    display: list-item;
  }
  .menu-ul {
    padding-right: 1.2em;
  }
}

ul, ul li {
  list-style: none;
}

 

 

代碼:

<template>
  <div class="demo2">
    <nav>
      <ul class="nav-ul">
        <li class="nav-item item-home">首頁</li>
      </ul>
      <ul class="nav-ul" @mouseover="showSubmenu = true" @mouseout="showSubmenu = false">
        <li class="nav-item item-demo1">導航高亮</li>
        <li class="menu" :style="{ display: showSubmenu ? 'block' : 'none' }">
          <ul class="menu-ul">
            <li>導航高亮-下級1</li>
            <li>導航高亮-下級2</li>
          </ul>
        </li>
      </ul>
      <ul class="nav-ul">
        <li class="nav-item item-demo2">導航懸浮顯示下級</li>
        <li class="menu">
          <ul class="menu-ul">
            <li>導航懸浮顯示下級-下級1</li>
            <li>導航懸浮顯示下級-下級2</li>
          </ul>
        </li>
      </ul>
    </nav>
  </div>
</template>

<script>
export default {
  name: 'demo-nav-hover-show1',
  data() {
    return {
      showSubmenu: false, // <-- 代碼僅做爲演示用
    };
  },
};
</script>

 

能夠看到,加了 mouse 事件後,鼠標懸浮後,會在元素的 style 中加上 display: none;,致使 css 中的樣式失效:

 

意外狀況:移動端 Safari 上,觸摸會觸發 CSS 的 hover,hover 會很高几率地先於 touchstart 事件,此時會判斷當前是顯示仍是隱藏狀態,因爲 CSS 的 hover 發揮了做用,因此判斷爲顯示,而後又把它隱藏了。也就是說,點一次不出來,要點兩次。因此最好別兩個同時寫。

 

 

代碼:

<div class="demo">
    <ul class="nav">
      <li class="nav-item item-home">
        <span>首頁</span>
      </li>
      <li class="nav-item item-demo">
        <span>鼠標懸浮顯示下級下拉菜單</span>
        <ul class="menu-ul">
          <li>導航懸浮顯示下級-下級1</li>
          <li>導航懸浮顯示下級-下級2</li>
        </ul>
      </li>
    </ul>
  </div>
.nav {
  padding: 5px 10px;
  background: #06a992;
  color: #fff;
}
.nav .nav-item {
  position: relative;
  display: inline-block;
  margin-right: 10px;
  list-style: none;
  opacity: 0.5;
  cursor: pointer;
  &:hover {
    opacity: 1;
    .menu-ul {
      display: block;
    }
  }
}
.demo .nav .nav-item.item-demo {
  opacity: 1;
}
.menu-ul {
  display: none;
  position: absolute;
  left: 0;
  top: 44px;
  min-width: 100px;
  padding-right: 1.2em;
  white-space: nowrap;
  border: 1px solid #000;
  box-shadow: 0 0 5px;
  color: #000;
  background-color: #fff;
  &:before { // <-- 加一個僞元素,能夠避免當下拉列表和導航菜單名稱之間有空隙時,鼠標往下移到下拉列表的過程當中,脫離導航菜單名稱而隱藏下拉列表的狀況
    content: "";
    position: absolute;
    left: 0;
    top: -20px;
    width: 100%;
    height: 20px;
  }
}
ul, ul li {
  list-style: none;
}

使用子元素的話,hover 可直接加在父容器上,隱藏元素自己不須要加 hover。

 

自定義 radio/checkbox 的樣式

可使用 :checked 代替鼠標點擊事件。

代碼:

<!--html-->
<div class="radio-checkbox">
  <label class="control-label">
    <input type="radio" value="value1" name="radio">
    radio1: <span class="radio"></span>
  </label>
  <label class="control-label">
    <input type="radio" value="value2" name="radio">
    radio2: <span class="radio"></span>
  </label>

  <label class="control-label">
    <input type="checkbox" value="value1">
    checkbox <span class="checkbox"></span>
  </label>
</div>
// less
input[type=checkbox],
input[type=radio] {
  display: none;
}
.control-label {
  margin-right: 10px;
  display: inline-block;
  cursor: pointer;
}
.radio {
  position: relative;
  display: inline-block;
  width: 16px;
  height: 16px;
  vertical-align: middle;
  border: 1px solid #3eaf7c;
  border-radius 50%;
}
input[type=radio]:checked + .radio {
  box-shadow: 0 0 3px #3eaf7c;
  &:after {
    content: '';
    width: 50%;
    height: 50%;
    display: block;
    position: absolute;
    left: 50%;
    top: 50%;
    transform: translateX(-50%) translateY(-50%);
    background: #3eaf7c;
    border-radius 50%;
  }
}
.checkbox {
  position: relative;
  display: inline-block;
  width: 16px;
  height: 16px;
  vertical-align: middle;
  border: 1px solid #3eaf7c;
}
input[type=checkbox]:checked + .checkbox {
  box-shadow: 0 0 3px #3eaf7c;
  &:after {
    content: '✓';
    display: block;
    position: absolute;
    left: 50%;
    top: 50%;
    transform: translateX(-50%) translateY(-50%);
    color: #3eaf7c;
  }
}

 

使用 :checked 屬性時,要注意兼容性

 

多列等高

padding 補償法

設置一個很大的 padding-bottom,這樣容器被最大的子元素撐開時,其餘的子元素使用能夠用 padding-bottom 來補償缺乏的高度。而後設置一個同方向的 margin-bottom 負值,能夠抵消設置的 padding-bottom。 同時設置父容器的 overflow: hidden;,將多餘的部分裁剪(隱藏)掉。

 

代碼:

<!--html-->
<div class="demo">
  <div class="col col1">
    <p class="title">蘋果</p>
    <p class="des">
      蘋果,是水果中的一種,是薔薇科蘋果亞科蘋果屬植物,其樹爲落葉喬木。
    </p>
  </div>
  <div class="col col2">
    <p class="title">香蕉</p>
    <p class="des">
      香蕉(學名:Musa nana Lour.)芭蕉科芭蕉屬植物,又指其果實,熱帶地區普遍種植。
    </p>
  </div>
  <div class="col col3">
    <p class="title">水蜜桃</p>
    <p class="des">
      水蜜桃(學名:Prunus persica 、meltingfleshed peach):薔薇科、桃屬植物。南方品種羣中肉質柔軟多汁呈軟溶質的一類品種。果實頂部平圓,熟後易剝皮,多粘核。
    </p>
  </div>
  <div class="col col4">
    <p class="title">菠蘿</p>
    <p class="des">
      菠蘿(學名:Ananas comosus),是熱帶水果之一。
    </p>
  </div>
</div>
// less
.demo {
  overflow: hidden;
}
.col {
  float: left;
  width: 20%;
  padding-top: 10px;
  padding-left: 10px;
  padding-right: 10px;
  padding-bottom 2000px; // <-- 設置 padding-bottom
  margin-bottom: -2000px; // <-- 設置 margin-bottom
  margin-right: 10px;
  border: 1px solid #000;
  border-radius: 5px;
}

 

缺點:底部的 border 沒有了,底部圓角也不顯示了。


table 佈局

table 中的每一個 td 都是等高的,因此能夠設置容器 display: table;,設置裏面的子元素 display: table-cell;。將子元素的寬度設大點,能夠實現等分。

 

 代碼:

// stylus
.demo
  display table
  border-spacing 20px // <-- 設置間隔
  word-break break-all
.col
  display table-cell
  width 1000px // <-- 設置很大的寬度,table 自動平分寬度
  padding: 10px
  border 1px solid #000
  border-radius 5px

注意:雖然 table 佈局能夠實現等分,可是有一種狀況須要注意,就是英文單詞很長,沒有設置 word-break 的時候,這種狀況是不會自動等分的。

這種佈局的另外一個好處,就是能夠在媒體查詢時,實現響應式。

能夠嘗試拉伸屏幕,觀察下面的佈局變化。(大屏顯示每行四列,中屏顯示每行兩列,小屏顯示每行一列。)

代碼:

<!--html-->
<div class="demo">
  <div class="col col1">
    <p class="title">蘋果</p>
    <p class="des">
      蘋果,是水果中的一種,是薔薇科蘋果亞科蘋果屬植物,其樹爲落葉喬木。
    </p>
  </div>
  <div class="col col2">
    <p class="title">香蕉</p>
    <p class="des">
      香蕉(學名:Musa nana Lour.)芭蕉科芭蕉屬植物,又指其果實,熱帶地區普遍種植。
    </p>
  </div>
  <!--加了個 tr 實現一行兩列布局-->
  <span class="tr"></span>
  <div class="col col3">
    <p class="title">水蜜桃</p>
    <p class="des">
      水蜜桃(學名:Prunus persica 、meltingfleshed peach):薔薇科、桃屬植物。南方品種羣中肉質柔軟多汁呈軟溶質的一類品種。果實頂部平圓,熟後易剝皮,多粘核。
    </p>
  </div>
  <div class="col col4">
    <p class="title">菠蘿</p>
    <p class="des">
      菠蘿(學名:Ananas comosus),是熱帶水果之一。
    </p>
  </div>
</div>
// stylus
.demo
  display table
  border-spacing 20px // <-- 設置間隔
  word-break break-all
.col
  display table-cell
  width 1000px // <-- 設置很大的寬度,table 自動平分寬度
  padding: 10px
  border 1px solid #000
  border-radius 5px
.tr
  display none
@media (max-width: 500px)
  .demo
    display block // <-- 能夠覆蓋原來的樣式,實現響應式佈局
  .col
    display block // <-- 能夠覆蓋原來的樣式,實現響應式佈局
    width: 100%
@media (max-width: 1024px) and (min-width: 501px)
  .tr
    display table-row // <-- 實現一行兩列布局

能夠看到,從一行兩列布局拉伸到寬屏時,.tr 的 display: none; 不起做用了。由於 table 佈局已經計算好了。要解決這個問題,須要藉助 JavaScript。

 

 代碼:

<!--html-->
<div class="demo">
  <div class="col col1">
    <p class="title">蘋果</p>
    <p class="des">
      蘋果,是水果中的一種,是薔薇科蘋果亞科蘋果屬植物,其樹爲落葉喬木。
    </p>
  </div>
  <div class="col col2">
    <p class="title">香蕉</p>
    <p class="des">
      香蕉(學名:Musa nana Lour.)芭蕉科芭蕉屬植物,又指其果實,熱帶地區普遍種植。
    </p>
  </div>
  <div class="col col3">
    <p class="title">水蜜桃</p>
    <p class="des">
      水蜜桃(學名:Prunus persica 、meltingfleshed peach):薔薇科、桃屬植物。南方品種羣中肉質柔軟多汁呈軟溶質的一類品種。果實頂部平圓,熟後易剝皮,多粘核。
    </p>
  </div>
  <div class="col col4">
    <p class="title">菠蘿</p>
    <p class="des">
      菠蘿(學名:Ananas comosus),是熱帶水果之一。
    </p>
  </div>
</div>
// less
.demo {
  display: flex;
  word-break break-all
  .col {
    width: 25%;
    padding: 10px;
    margin: 0 10px;
    border: 1px solid #000;
    border-radius: 5px;
  }
}

 

根據個數顯示不一樣樣式

需求:

例若有 1 ~ 3 個 item 顯示在同一行,但 item 的個數不必定,若是隻有 1 個,那 item 佔寬 100%;若是有 2 個,每一個佔 50%;若是有 3 個,每一個佔 33%。

:nth-last-child(an+b) 這個 CSS 僞類匹配文檔樹中在其以後具備 an+b-1 個兄弟節點的元素,其中 n 爲正值或零值。它基本上和 :nth-child 同樣,只是它從結尾處反序計數,而不是從開頭處。MDN

 

代碼:

<!--html-->
<div class="demo">
  <ul class="list clearfix">
    <li class="list-item">一行 1 個</li>
  </ul>
  <ul class="list clearfix">
    <li class="list-item">一行 2 個</li>
    <li class="list-item">一行 2 個</li>
  </ul>
  <ul class="list clearfix">
    <li class="list-item">一行 3 個</li>
    <li class="list-item">一行 3 個</li>
    <li class="list-item">一行 3 個</li>
  </ul>
</div>
// less
.demo {
  width: 100%;
  .list {
    .list-item {
      display: inline-block;
      float: left;
      text-align: center;
      border: 1px solid #000;
      box-sizing: border-box; // <-- 設置 box-sizing
      background-color: #4abf8a;
      &:nth-child(2) {
        background-color: #3a8ee6;
      }
      &:nth-child(3) {
        background-color: yellow;
      }
      width: 100%; // <-- 一行顯示一個時,使用該樣式
      &:first-child:nth-last-child(2),
      &:first-child:nth-last-child(2) ~ .list-item { // <-- 一行顯示兩個時,使用該樣式,&:first-child:nth-last-child(2) 指向第一個元素
        width: 50%;
      }
      &:first-child:nth-last-child(3),
      &:first-child:nth-last-child(3) ~ .list-item { // <-- 一行顯示兩個時,使用該樣式,&:first-child:nth-last-child(2) 指向第一個元素
        width: 33.3%;
      }
    }
  }
}

 

須要注意的是,若是 item 有 border,這樣設置是不行的,由於 border 也會佔據必定的寬度。設置一下 box-sizing: border-box; 便可。

 

需求:

手機屏幕比較小,左邊圖標比較多,一行排不下,把右邊的電話換行,隱藏豎線。(左邊圖標個數不定)

感受需求描述不完整,想象不出這種場景,沒法實現代碼。

巧用 CSS3 僞類(pseudo class)

  • :focus
  • :invalid

 

代碼:

<!--html-->
<form class="form">
  <p>利用 :focus 僞類實現 focus 時,放大鏡顏色加深。</p>
  <div class="form-group">
    <label for="search" class="form-label"></label>
    <div class="form-control">
      <input class="form-control-input" id="search" type="text">
      <i class="icon-search fas fa-search"></i>
    </div>
  </div>
  <p>利用 :invalid 僞類進行校驗。</p>
  <div class="form-group">
    <label for="email" class="form-label"></label>
    <div class="form-control">
      <input class="form-control-input" id="email" type="email">
      <span class="btn">Next</span>
    </div>
  </div>
</form>
// less
.form-control {
  position: relative;
}
.form-control-input {
  padding: 0 32px;
  &:focus + .icon-search { // <-- :focus 僞類
    color: #3eaf7c;
  }
  &:invalid + .btn { // <-- :invalid 僞類
    opacity: .5;
    cursor: default;
  }
}
.icon-search {
  position: absolute;
  left: 10px;
  top: 14px;
  color: #ddd;
}
.btn {
  height: 40px;
  line-height: 1.5;
  padding: 5px 10px;
  position: absolute;
  right: 0;
  top: 0;
  transform: translateX(100%);
  border: 1px solid #3eaf7c;
  border-radius: 3px;
  background: #3eaf7c;
  color: #fff;
  cursor: pointer;
}

 

其餘

需求:

hover 時顯示提示信息。不想用 title,也不想用 JavaScript,更不想引入第三方庫。

 

代碼:

<!--html-->
<p>
  Hello
  <span class="tip" data-title="Frontend Development">FED</span>
</p>
// less
.tip {
  position: relative;
  &:hover:before {
    padding: 5px;
    content: attr(data-title);
    position: absolute;
    left: 50%;
    top: -230%;
    transform: translateX(-50%);
    white-space: nowrap;
    border-radius: 5px;
    background: #000;
    color: #fff;
  }
  &:hover:after {
    position: absolute;
    top: -10px;
    left: 50%;
    transform: translateX(-50%);
    content: '';
    width: 0;
    height: 0;
    border-style: solid;
    border-width: 12px;
    border-color: transparent;
    border-top-color: #000;
  }
}
相關文章
相關標籤/搜索