iT邦幫忙

0

[AC作業] 切版挑戰記錄: 添加選擇樣式 + 如何固定table header

  • 分享至 

  • xImage
  •  

前言:

此次作業紀錄要完成課程 demo的廣告系統:作業切版挑戰
作業預計時間是兩小時,需要完成以下兩個項目:

廣告被選擇時的樣式

固定 table header

完成作品畫面如下:
https://ithelp.ithome.com.tw/upload/images/20221209/20153933nVXYWA92BG.jpg

第一項花了一小時完成,覺得開心,想說第二項看起來很簡單......結果我整個卡住 !
第二項花了約三小時才完成 /images/emoticon/emoticon17.gif

回正文

如何使欄位被選擇時添加樣式呢?

第一個想法最近常練習的: 添加一個 className給要被選擇的樣式
推想流程:
首先,我是先尋找哪一個節點需要被定義樣式 --> 找到tbody tr
確認要被當作目標的 checkbox
要被綁定的是 每一個checkbox (for loop)
當元素被點選後的變化是 checkbox的父元素

定義一個className: selectedRow,並先試著在我要選取的該欄 tr 試加 selectedRow 的class 確定效果

.selectedRow {
  background: var(--main-color);
}

PS. 這邊使用的 var(--main-color) 是因為此專案有把所有的數字(CSS color 色號) 變數化,方便管控
https://ithelp.ithome.com.tw/upload/images/20221209/20153933AWkRCh2S9x.jpg

定義好className, 接著來選定checkbox 目標,透過提供 callback函數的方式對 "change"事件新增處理器
使用 for loop 迴圈才可以綁定每一欄的checkbox
每一次 checkbox被點選"change",則會觸發 selectedItem函數

// target the check box
const checkbox = document.querySelectorAll(".table_cell--checkbox");
//bind the event(use for loop)
for (let i = 1; i < checkbox.length; i++) {
  checkbox[i].addEventListener("change", selectedItem);
}

function selectedItem(element) {
  // console.log('element:', element.target.parentElement.parentElement)
  const selectedOneRow = element.target.parentElement.parentElement;
  selectedOneRow.classList.toggle("selectedRow");
}

為什麼用change? change事件是可以將checkbox表單元素在被改變時觸發,input 事件會在輸入框輸入內容的當下被觸發,但是change事件則是在目前焦點離開輸入框後才觸發。
(參考文章: 重新認識 JavaScript: Day 16 那些你知道與不知道的事件們)

如何使用純CSS將表格凍結首欄?

嘗試過程:

(1) 失敗的position:fixed

一開始嘗試Position: fixed, 雖固定了該欄,但thead欄位float,長寬也跑掉
起始位置沒有在第一行資料的上面
因為Fixed會定位在原本的位置,並在空間中被抽出位置,故被定位的thead會被後面的內容忽視,自動往前跑。
並且fixed的欄設置位置(top/bottom/right/left)時會以視窗來做定位
--> 故要把tbody的第一行位置往下推,但是寬度依然失效,網路上搜尋只找到如何配合父層視窗做width:100%

所以我再搜尋固定table header, 大多看到jquery和純CSS的文章或討論串
我去研究找純css的,看到許多人推 position:sticky + top: 0
但我的那一行thead 怎麼樣都沒有留在最上方啊啊啊啊啊

(2) 不懂裝懂的position:sticky + top: 0

參照stackoverflow的討論串作了以下一版,但沒有很了解為什麼這樣寫的做法,一樣失敗,而且只有部分幾格欄位有被凍結首行,也不是在top: 0

main {
  overflow: scroll;
}

table {
  position: relative;
  border-collapse: collapse;
}

thead th {
  position: -webkit-sticky;
  position: sticky;
  top: 0;
  background: var(--header-color);
  color: var(--header-text-color);
}

tbody td:first-child {
  position: -webkit-sticky;
  position: sticky;
  left: 0;
}

(3) 呈上,我從CSS-tricks 找到了失敗原因: CSS-tricks 參考資料

**The issue boils down to the fact that stickiness requires position: relative to work and that doesn’t apply to <thead> and <tr> in the CSS 2.1 spec.**

啊! 原來thead和tr 不被支援 position:sticky
刪除了thead 關鍵字依然卡在漂浮

(4) 最後我找了這篇! 用position:sticky凍結欄位(th)

標題很清楚寫了解決重點:"用position:sticky凍結欄位(th) sticky會跟著上一層的overfloat跑!!因此要定義一個外框(class="table-sticky-wrapper")"

將外面包一層div,定義寬高並且將首欄的th (z-index: 2) 和tbody的td (z-index: 1) 設出區別
就可以把裡面表格凍結首欄了!
成功了! 只是跟一開始想的不太一樣現在變成外面有scroll 裡面表格也有scroll, 覺得不好看~~

所以我將外層包的div 縮小高度,讓外層的高度不會因過高而產生overflow 的問題

.table_sticky_wrapper {
  width: 100%;
  height: 70vh; //這個div的高度
  overflow: auto;
}

.main_table {
  position: relative;
  border-collapse: collapse;
}

.main_table th {
  position: sticky;
  top: 0;
  background: var(--header-color);
  vertical-align: center;
  border-bottom: 0;
  z-index: 2;
}

tbody td {
  left: 0;
  z-index: 1;
}

成品示意圖: 因為我不太想要scroll bar出現,所以就試著把它隱藏掉,順便練習一下如何修改scroll-bar樣式

我的成品codepen

以上是我這次的學習記錄整理
雖然中間幾個嘗試方式沒有成功,但我都有從那些文章複習或領悟到一些觀念
所以一起放上來~
有任何錯誤再麻煩指正~
/images/emoticon/emoticon41.gif


圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言