整合營銷服務商

          電腦端+手機端+微信端=數據同步管理

          免費咨詢熱線:

          動手練一練,手寫一個價格對比、固定表頭滾動的表格

          動手練一練,手寫一個價格對比、固定表頭滾動的表格


          家好,今天我們將一起實踐下如何手寫固定表頭,那么什么是固定表頭呢?就類似 Excel 表格有個鎖定表頭的功能,方便用戶查閱數據進行數據項的對比。雖然有不少相關插件提供了類似的功能,比如 ScrollMagic.js,但是今天的實例,我們將用純原生的方式進行實現,當滾動條滾動至表格位置,固定表頭位置,表格內容查看完后,取消固定表頭的功能。

          一、實踐一個功能價格對比的表格案例

          功能對比是一個很常用的功能,尤其是當網站服務越來越多時,就需要一個類似的功能,讓用戶能夠直觀的感受到各種服務的差異,幫助用戶選擇適合自己的方案。今天我們將通過一個界面十分漂亮功能價格對比的表格,展示固定表頭的功能,實例操作展示如視頻所示,當滾動條滾動至表格位置,添加表頭固定樣式,當滾動至表格底部,移除固定表頭樣式:

          <script src="https://lf6-cdn-tos.bytescm.com/obj/cdn-static-resource/tt_player/tt.player.js?v=20160723"></script>

          二、案例相關知識點復習

          這篇案例我們是通過JS代碼,判斷滾動條的位置,動態添加和移除表頭的固定樣式(fix屬性),這里就需要運用幾個和位置相關 DOM API 才能順利完成本案例,相關 API 介紹如下所示:

          1、Window pageXOffset 和 pageYOffset 屬性

          pageXOffset 和 pageYOffset 屬性返回文檔在窗口左上角水平和垂直方向滾動的像素。

          pageXOffset 設置或返回當前頁面相對于窗口顯示區左上角的 X 位置。pageYOffset 設置或返回當前頁面相對于窗口顯示區左上角的 Y 位置。

          pageXOffset 和 pageYOffset 屬性相等于 scrollX 和 scrollY 屬性。

          2、clientHeight、offsetHeight、scrollHeight、offsetTop、scrollTop

          clientHeight:包括 padding 但不包括border、水平滾動條、margin的元素的高度。對于inline的元素這個屬性一直是0,單位px,只讀元素。

          offsetHeight:包括padding、border、水平滾動條,但不包括margin的元素的高度。對于inline的元素這個屬性一直是0,單位px,只讀元素。

          scrollHeight: 因為子元素比父元素高,父元素不想被子元素撐的一樣高就顯示出了滾動條,在滾動的過程中本元素有部分被隱藏了,scrollHeight代表包括當前不可見部分的元素的高度。而可見部分的高度其實就是clientHeight,也就是scrollHeight>=clientHeight恒成立。在有滾動條時討論scrollHeight才有意義,在沒有滾動條時scrollHeight==clientHeight恒成立。單位px,只讀元素。

          scrollTop: 代表在有滾動條時,滾動條向下滾動的距離也就是元素頂部被遮住部分的高度。在沒有滾動條時scrollTop==0恒成立。單位px,可讀可設置。

          offsetTop:當前元素頂部距離最近父元素頂部的距離,和有沒有滾動條沒有關系。單位px,只讀元素。

          本部分內容摘自

          https://imweb.io/topic/57c5409e808fd2fb204eef52

          作者:IMWeb

          吳浩麟

          3、getBoundingClientRect

          getBoundingClientRect 用于獲得頁面中某個元素的左,上,右和下分別相對瀏覽器視窗的位置。getBoundingClientRect是DOM元素到瀏覽器可視范圍的距離(不包含文檔卷起的部分)。

          3.1、該函數返回一個Object對象,該對象有6個屬性:top,lef,right,bottom,width,height;

          3.2、這里的top、left和css中的理解很相似,width、height是元素自身的寬高;

          3.3、但是right,bottom和css中的理解有點不一樣。right是指元素右邊界距窗口最左邊的距離,bottom是指元素下邊界距窗口最上面的距離。

          本部分內容摘自:

          https://juejin.im/entry/59c1fd23f265da06594316a9

          作者:左鵬飛

          三、創建 HTML 基礎結構

          1、創建三個基礎的 sections 的區域

          <section>...</section>
          <section>...</section>
          <section>...</section>
          

          第一部分為頁面標題內容,第三部分為內容介紹區域,這兩部分非核心內容,只是用于內容占位,方便第二部分表格區域的展示,滾動此區域表頭固定。

          2、表格內容結構

          我們將第二部分的表格放置在 container 的容器內,方便我們做響應式相關的設置,表格基礎結構的內容如下:

          <div class="container">
            <div class="table-wrapper">
              <table>
                <thead>
                  <tr>
                    <th>...</th>
                    <th>...</th>
                    <th>...</th>
                    <th>...</th>
                  </tr>
                </thead>
                <tbody>
                  <tr>
                    <td>...</td>
                    <td>...</td>
                    <td>...</td>
                    <td>...</td>
                  </tr>
                   
                  <!-- more rows here -->
                </tbody>
              </table>
            </div>
          </div>
          

          該表格包含4列,代表產品服務的對比項目和服務的級別,服務級別包含:入門級,基礎級和專業級。

          3、表頭內容結構

          表頭部分應該很清楚的展示服務項目的介紹,讓用戶有購買服務計劃的沖動,界面展示如下所示:

          相關的 HTML 結構如下所示:

          <tr>
            <th>
              <div>
                Select your plan
                <div class="svg-wrapper">
                  <svg viewBox="0 0 24 24"><path d="M12 0c-6.627 0-12 5.373-12 12s5.373 12 12 12 12-5.373 12-12-5.373-12-12-12zm1 17v-4h-8v-2h8v-4l6 5-6 5z"/></svg>
                </div>
              </div>
            </th>
            <th>
              <div class="heading">...</div>
              <div class="info">
                <div class="amount">...</div>
                <div class="billing-msg">...</div>
                <button type="button">...</button>
              </div>
            </th>
            <th>
              <div class="heading">...</div>
              <div class="info">
                <div class="popular">...</div>
                <div class="amount">...</div>
                <div class="billing-msg">...</div>
                <button type="button">...</button>
              </div>
            </th>
            <th>
              <div class="heading">...</div>
              <div class="info">
                <div class="amount">...</div>
                <div class="billing-msg">...</div>
                <button type="button">...</button>
              </div>
            </th>
          </tr>
          

          4、表格相關的行

          每行內容描述服務內容中相關的功能是否能用,這里用 SVG圖標(對號,叉號)進行直觀展示,界面展示如下圖所示:

          相關的 HTML 結構如下所示:

          <tr>
            <td>...</td>
            <td>
              <svg class="starter" viewBox="0 0 24 24"><path d="M12 0c-6.627 0-12 5.373-12 12s5.373 12 12 12 12-5.373 12-12-5.373-12-12-12zm-1.959 17l-4.5-4.319 1.395-1.435 3.08 2.937 7.021-7.183 1.422 1.409-8.418 8.591z"/></svg>
            </td>
            <td>
              <svg class="essential" viewBox="0 0 24 24"><path d="M12 0c-6.627 0-12 5.373-12 12s5.373 12 12 12 12-5.373 12-12-5.373-12-12-12zm-1.959 17l-4.5-4.319 1.395-1.435 3.08 2.937 7.021-7.183 1.422 1.409-8.418 8.591z"/></svg>
            </td>
            <td>
              <svg class="professional" viewBox="0 0 24 24"><path d="M12 0c-6.627 0-12 5.373-12 12s5.373 12 12 12 12-5.373 12-12-5.373-12-12-12zm-1.959 17l-4.5-4.319 1.395-1.435 3.08 2.937 7.021-7.183 1.422 1.409-8.418 8.591z"/></svg>
            </td>
          </tr>
          

          四、定義樣式

          1、定義基礎樣式

          HTML結構準備好后,接下來我們定義相關基礎的 CSS 樣式,比如定義 CSS 自定義變量和常見的重置樣式,示例代碼如下:

          :root {
            --white: white;
            --gray: #999;
            --lightgray: whitesmoke;
            --popular: #ffdd40;
            --starter: #f73859;
            --essential: #00AEEF;
            --professional: #FF7F45;
          }
           
          * {
            padding: 0;
            margin: 0;
            box-sizing: border-box;
          }
           
          button {
            background: none;
            border: none;
            cursor: pointer;
          }
           
          table {
            border-collapse: collapse;
          }
           
          body {
            font: 18px/1.5 'Noto Sans', sans-serif;
            background: var(--lightgray);
          }
          

          由于文章篇幅有限,這里不會將所有的 CSS 代碼進行羅列,這里只介紹最核心的樣式內容。

          2、定義表格樣式

          首先定義表格最大寬度,然后讓其水平居中:

          .container {
            max-width: 850px;
            padding: 0 10px;
            margin: 0 auto;
          }
           
          table {
            width: 100%;
          }
          

          接下來讓行的容器為 flex 彈性盒子布局

          table tr {
            display: flex;
          }
          

          然后讓每列保持相同寬度,示例代碼如下:

          table th,
          table td {
            width: 25%;
            min-width: 150px;
          }
          

          最后為了讓單元格區域便于識別,我們用灰色邊框進行區分,示例代碼如下:

          --lightgray: whitesmoke;
           
          table th .info,
          table td:not(:first-child) {
            border-left: 1px solid var(--lightgray); 
          }
          

          五、編寫固定表頭的相關腳本

          HTML結構和CSS完成后,接下來我們編寫腳本固定表頭。

          1、定義DOM變量

          首先我們先定義一些關鍵DOM元素的變量,比如獲取表格、表頭等元素,示例代碼如下:

          const body=document.body;
          const firstSection=document.querySelector("section:nth-child(1)");
          const lastSection=document.querySelector("section:nth-child(3)");
          const table=document.querySelector("table");
          const thead=document.querySelector("table thead");
          const mq=window.matchMedia("(min-width: 780px)");
          const stickyClass="sticky-table";
          const sticky2Class="sticky2-table";
          

          2、獲取一些元素相關的值

          • 獲取表格的 offsetWidth 寬度
          • 獲取表格距離視口頂部的距離(getBoundingClientRect().top)
          • 獲取表頭的 offsetHeight 高度

          基于這些我們定義相關的變量,獲取相關的值:

          let tableWidth=table.offsetWidth;
          let tableOffsetTop=table.getBoundingClientRect().top;
          let theadHeight=thead.offsetHeight;
          

          你可能注意到了這里我們使用 let 定義變量,之所以用 let ,我們改變窗口的大小,這些相關的值也會發生變化,需要進行動態更新。

          3、編寫滾動的相關邏輯

          每次我們滾動時,就會執行我們定義的 scrollHandler 函數,我們這個函數只會在窗口寬度大于 780px 才會執行固定表頭的邏輯,小屏設備則沒有相關效果。

          1. 獲取用戶從視口頂部滾動的距離(pageYOffset)
          2. 獲取最后一部分內容區域距離窗口頂部的高度(getBoundingClientRect().top)
          3. 檢測滾動條是否滾動到表格區域。
          4. 如果滾動到表格區域,獲取重置后的表頭寬度。
          5. 接下來我們來判斷第三部分內容區域距離視口頂部的高度是否大于表頭的高度。
          6. 如果還在滾動表格的內容,我們將添加固定表頭的樣式stickyClass,移除取消固定的樣式sticky2-table。
          7. 如果滾動條滾動至第三部分內容區域,我們將移除固定表頭的樣式stickyClass,添加移除固定表頭的樣式 sticky2-table。
          8. 如果屏幕寬度小于780px,取消固定表頭的邏輯,移除stickyClass,sticky2-table 相關的樣式

          基于以上邏輯我們實現相關的代碼邏輯:

          window.addEventListener("scroll", scrollHandler);
           
          function scrollHandler() {
            if (mq.matches) {
              // 1
              const scrollY=window.pageYOffset;
              // 2
              const lastSectionOffsetTop=lastSection.getBoundingClientRect().top;
              // 3
              if (scrollY >=tableOffsetTop) {
                // 4
                thead.style.width=`${tableWidth}px`;
                // 5
                if (lastSectionOffsetTop > theadHeight) {
                  // 6
                  body.classList.remove(sticky2Class);
                  body.classList.add(stickyClass);
                  thead.style.top=0;
                  body.style.paddingTop=`${theadHeight}px`;
                } else {
                  // 7
                  body.classList.remove(stickyClass);
                  body.classList.add(sticky2Class);
                  thead.style.top=`calc(100% - ${theadHeight}px)`;
                }
              } else {
                // 8
                body.classList.remove(stickyClass, sticky2Class);
                body.style.paddingTop=0;
                thead.style.width="100%";
                thead.style.top="auto";
              }
            }
          }
          

          編寫相關的樣式代碼,stickyClass 和 sticky2-table 控制表頭的固定和取消表頭的固定

          table thead {
            transition: box-shadow 0.2s;
          }
           
          .sticky-table table thead {
            position: fixed;
            left: 50%;
            transform: translateX(-50%);
          }
           
          .sticky-table table thead {
            box-shadow: 0px 3px 6px rgba(0, 0, 0, 0.12);
          }
           
          .sticky2-table table thead {
            position: absolute;
            left: 0;
          }
          

          六、編寫窗口大小發生變化的相關邏輯

          由于窗口大小并非固定,我們會經常會拖動或調整窗口的大小,因此相關元素的寬度和視口高度都要重新計算,這里我們需要添加 resize 事件進行監聽,示例代碼如下:

          window.addEventListener("resize", resizeHandler);
           
          function resizeHandler() {
            if (mq.matches) {
              tableWidth=firstSection.offsetHeight;
              tableOffsetTop=table.offsetTop; 
              theadHeight=thead.offsetHeight;
            } else {
              body.classList.remove(stickyClass, sticky2Class);
              body.style.paddingTop=0;
              thead.style.width="100%";
              thead.style.top="auto";
            }
          }
          

          七、源碼及效果展示

          最終的效果體驗,大家可以點擊文末 了解更多 鏈接進行體驗(手機橫屏體驗),由于文章篇幅有限,完整的源碼大家可以私信“表頭”獲取源碼鏈接。

          小節

          到此,我們一起完成了這個案例,通過本案例,我們學會了如何使用原生的方式動態實現固定元素,并在一定的時機取消固定。感謝你的閱讀,如果你喜歡我的分享,麻煩給個關注、點贊加轉發哦,你的支持,就是我分享的動力,后續會持續分享更實用的案例,歡迎持續關注。

          文章來源:

          作者:George Martsoukos

          網站:tutsplus

          非直譯


          相關閱讀

          動手練一練,用 CSS Checkbox Hack 技術制作一個響應式圖片幻燈

          動手練一練,做一個現代化、響應式的后臺管理首頁

          動手練一練,使用 Flexbox 創建一個響應式的表單

          動手練一練,用純 CSS 制作一款側滑顯示留言面板的網頁組件

          使用 Vanilla JavaScript 框架創建一個簡單的天氣應用

          使用 CSS Checkbox Hack 技術制作一個手風琴組件

          lt;thead>標簽定義HTML中<table>元素的標題;

          <thead>標簽與<tbody>和<tfoot>標簽一起使用,它們定義HTML表格中的表頭,表主體和表腳。

          <thead>標簽作為<table>標簽的子元素,需出現在<caption>、<colgroup>元素之后;<tbody>,<tr>或<tfoot>元素之前。

          <thead>標記內應至少包含一行<tr>元素。

          提示:<thead>、<tbody>和<tfoot>元素默認不會影響表格的布局。不過可以使用CSS來為這些元素定義樣式,從而改變表格的外觀。

          語法格式

          <thead>

          <tr>……</tr>

          <thead>

          示例代碼

          <table border="1">
              <caption>圖書大廈書目價格單</caption>  
              <thead>  
                  <tr>  
                      <th>書名</th>  
                      <th>單價</th>  
                  </tr>  
              </thead>  
              <tr>  
                  <td>HTML入門教程</td>  
                  <td>79.00元</td>  
              </tr>  
              <tr>  
                  <td>JavaScript基礎教程</td>  
                  <td>46.00元</td>  
              </tr>  
              <tr>  
                  <td>Python精品教程</td>  
                  <td>99.00元</td>  
              </tr>  
          </table>  123456789101112131415161718192021復制代碼類型:[html]

          效果展示:

          圖書大廈書目價格單

          書名

          單價

          HTML入門教程

          79.00元

          JavaScript基礎教程

          46.00元

          Python精品教程

          99.00元

          HTML4.01與HTML5差異

          在HTML5中,不再支持HTML4.01中<thead>標簽的任何屬性。

          瀏覽器支持

          所有主流瀏覽器都支持<thead>標簽。

          標簽屬性

          屬性

          描述

          align

          right
          left
          center
          justify
          char

          HTML5 不支持。定義 <thead> 元素中內容的對齊方式。

          char

          character

          HTML5 不支持。規定 <thead> 元素中內容根據哪個字符來對進行文本對齊。

          charoff

          number

          HTML5 不支持。規定 <thead> 元素中內容的第一個對齊字符的偏移量。

          valign

          top
          middle
          bottom
          baseline

          HTML5 不支持。規定 <thead> 元素中內容的垂直對齊方式。

          全局屬性

          <thead>標簽支持HTML的全局屬性。

          事件屬性

          <thead>標簽支持HTML的事件屬性。

          開課吧廣場-人才學習交流平臺

          emo代碼:

          <!DOCTYPE html>
          <html>
            <head>
              <meta charset="utf-8" />
              <title>el-table動態表頭</title>
              <link rel="stylesheet" type="text/css" href="./lib/element-ui/theme-chalk/index.css" />
            </head>
            <body>
              <div id="app">
          			<el-table
                  :data="tableBody"
                  :header-cell-style="{ background: '#F3F4F7' }"
                  :header-row-style="{ fontWeight: 500, color: '#909399' }"
                >
                  <el-table-column align="center" :label="tableHeadItem" v-for="(tableHeadItem, idx) in tableHead" :key="idx">
                    <template scope="scope">
                      <i class="el-icon-platform-eleme" style="font-size: 16px"></i>
                      {{tableBody[scope.$index][idx]}}
                    </template>
                  </el-table-column>
                </el-table>
              </div>
              <script src="./lib/vue/vue.js"></script>
              <script src="./lib/element-ui/index.js"></script>
              <script type="text/javascript">
                new Vue({
                  el: "#app",
                  data() {
                    return {
                      res: [
                        {
                          NAME: "王二",
                          VALUE: 1,
                          SEX: 2,
                        },
                        {
                          NAME: "張三",
                          VALUE: 1,
                          SEX: 1,
                        },
                        {
                          NAME: "李四",
                          VALUE: 2,
                          SEX: 1,
                        },
                      ],
                      tableBody: [],
                      tableHead: [],
                    };
                  },
                  created() {
          					this.tableHead=Object.keys(this.res[0]);  // 表頭 [ "NAME", "VALUE", "SEX" ]
                    this.res.forEach((item)=> {
                      this.tableBody.push(Object.values(item));  // 表體  [ ["王二", 1, 2], ["張三", 1, 1], ["李四", 2, 1] ]
          					});
                  },
                });
              </script>
            </body>
          </html>

          動態表格是生成列,也就是每一個<el-table-column>然后再根據所有列去遍歷生成行,這樣一個過程,知道這些,要做的就是根據這么一個過程去生成這樣一個數據格式就行了。

          實現動態表格的延伸:

          element-ui官方推薦的CDN引入使用element的任務組件都是沒有問題的,但是如果將樣式和組件庫代碼下載下來改為本地引入,icon組件將不能使用!

          CDN引入:

          <!-- 引入樣式 -->
          <link rel="stylesheet" href="https://unpkg.com/element-ui/lib/theme-chalk/index.css">
          <!-- 引入組件庫 -->
          <script src="https://unpkg.com/element-ui/lib/index.js"></script>

          請求資源:

          請求的網絡資源中多了一個element-icons.woff文件,原因:查看element中index.css中的icon的引入方式。

          @font-face {
            font-family: element-icons;
            src: url(fonts/element-icons.woff) format("woff"), url(fonts/element-icons.ttf) format("truetype");
            font-weight: 400;
            font-display: "auto";
            font-style: normal;
          }

          解決方法:

          復制字體圖標資源鏈接下載下來,然后在element的index.css文件夾同級目錄中新建fonts文件夾放入下載好的element-icons.woff和element-icons.ttf字體圖標文件。


          主站蜘蛛池模板: 国产自产V一区二区三区C| 日美欧韩一区二去三区| 久久中文字幕一区二区| 国产一区二区三区夜色| 久久久久人妻精品一区三寸蜜桃| 91久久精一区二区三区大全| 亚洲爆乳无码一区二区三区| 国产福利一区二区三区| 精品视频一区二区观看| 国产精品无码AV一区二区三区| 久久国产精品无码一区二区三区 | 人妻久久久一区二区三区| 伊人色综合一区二区三区影院视频| 成人精品视频一区二区| 亚洲国产成人久久综合一区77| 久久久久人妻精品一区蜜桃| 国产精品久久无码一区二区三区网| 国产成人精品a视频一区| 亚洲一区二区电影| 精品一区二区高清在线观看| 一区二区三区亚洲| 波多野结衣在线观看一区二区三区| 成人免费区一区二区三区| 久久精品国内一区二区三区| 成人无码AV一区二区| 成人国产精品一区二区网站公司| 成人精品视频一区二区三区不卡 | 亚洲国产av一区二区三区| 91亚洲一区二区在线观看不卡| 精品在线一区二区| 乱子伦一区二区三区| 一区二区三区四区视频在线| 精品国产鲁一鲁一区二区| 国产韩国精品一区二区三区| 亚洲日韩AV无码一区二区三区人 | 国产在线aaa片一区二区99| 午夜视频一区二区| 亚洲日本一区二区| 中日韩一区二区三区| 国产一区韩国女主播| 99久久精品午夜一区二区|