# CSS 小撇步 ### 練習網站 [CSS 選取器練習](https://flukeout.github.io/) ### 有用觀念的雜紀 * HTML 結構的層級關係在寫 CSS 的時候要留意一些往子層觸發的事件,例如說 hover 的時候要顯示出來,往子層都沒關係,但若顯示的是同層或是上層就會出問題,解法為用 JS 去動態選取元素在 hover 的時候添加 display:block > JQ 的 hover() 要帶兩個函式參數,分別為 mouseenter 跟 mouseleave 兩個事件 ### 01.reload 進場動畫 進入後透過讓整個 body 從透明度 0 到 1 過場形成淡入效果。 ```css= body { animation: fade-in-page 0.75s linear; @keyframes fade-in-page { 0% { filter: blur(5px); opacity: 0; } 100% { filter: blur(0); opacity: 1; } } } ``` --- ### 02.數字計數動畫 使用函式庫 CountUp.js,這邊的用法好像是將傳入的結束值作為最終顯示。 [github 位置](https://github.com/inorganik/countUp.js) 1. 引入函式庫 2. 創建 CountUp 物件 3. 將設定改為參數傳入 function 4. 需執行的 tag 要寫上 id (還沒測試其他選取器是否可行) ```htmlembedded= <span class="number" id="counter01">3</span> <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script> <script src='https://cdnjs.cloudflare.com/ajax/libs/countup.js/1.8.2/countUp.min.js'></script> ``` ```javascript= function countUp (id,start,end,duration) { let options = { useEasing: true, useGrouping: true, }; let demo = new CountUp(id,start,end,0,duration,options); (!demo.error) ? demo.start() : console.error(demo.error); } } countUp("counter01",0,3,2.5); ``` 也可以用 CSS animation 硬幹 [範例](https://codepen.io/yyaann/pen/abpeEjy) --- ### 03.進場動畫 使用函式庫 Animate.css [Animate.css](https://animate.style/) 1. CDN 引入 2. 直接在 tag 上加 class,也可以寫在 CSS 的 animation 內 --- ### 04.img 的 CSS reset RWD 時寫上讓圖片自適應伸縮 ```css= img { max-width: 100%; height: auto; } ``` --- ### 05.讓用戶不用掃描,直接點就可以加 line 好友的方式 [參考這邊](https://study.smallway.tw/%E7%A8%8B%E5%BC%8F%E8%AA%9E%E6%B3%95/%E3%80%90code%E3%80%91html%E5%8A%A0line%E5%A5%BD%E5%8F%8B%E7%9A%84%E8%AA%9E%E6%B3%95%EF%BC%8C%E8%AB%8B%E6%94%B9%E7%94%A8%E9%80%99%E5%80%8B%E6%9B%B4%E8%83%BD%E5%A2%9E%E5%8A%A0%E6%88%90%E5%8A%9F/) 在 a 連結那邊的方式改寫成以下 * 原本的加好友連結是這樣 : http://line.me/ti/p/@329doqml * 請你改成這樣 : line://ti/p/@329doqml --- ### 06.SCSS 的設定方式 [參考這邊](https://medium.com/@enshenghuang/%E4%BD%BF%E7%94%A8vscode%E5%A4%96%E6%8E%9B%E8%87%AA%E5%8B%95%E7%B7%A8%E8%AD%AFsass-scss-9ff768d23b48) --- ### 07.版面高度的設定問題 最上層的元素不該設定高度 ex:120vh,應該要讓內容物自適應去撐高度才對,不然當裝置寬變窄後內容物往下擠就會出現高不夠讓內容被吃掉的情況。 而上下的間距則透過上下的子元素做 margin 來撐即可。 --- ### 08.漢堡下拉選單實現方式 1. 下拉選單起出藏在畫面外部 2. 點擊漢堡時改變 class 將 display:none 改為 block 3. 用 JS 的 click 動態改變 class 4. 或是用純 CSSS 的 input:checked 狀態或是 hover 跟 active 來控制 --- ### 09.Scroll 事件偵測 --- ### 10.Scroll 觸發動畫套件 AOS 如何使用 AOS ? [AOS](https://michalsnik.github.io/aos/) CDN 腳本跟樣式表 ```htmlembedded= <link href="https://unpkg.com/aos@2.3.1/dist/aos.css" rel="stylesheet"> <script src="https://unpkg.com/aos@2.3.1/dist/aos.js"></script> ``` 在標籤內加上 data-key 的屬性,也可在此調整參數 ```htmlembedded= // 一般 <img class="color-arrow" src="Content/img/color-arrow.svg" alt="" data-aos="fade-right" data-aos-delay="300"> // SVG 自訂動畫 <div class="svg-area " data-aos="anim-line"> <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 855.46 871.04"> <g> <polygon id="one" points="566.52 0.93 397.24 381.83 684.75 381.83 854.03 0.93 566.52 0.93" /> <polygon id="two" points="397.24 381.83 218.43 381.83 1.43 870.11 180.23 870.11 397.24 381.83" /> </g> </svg> </div> ``` 範例比較複雜,要讓 SVG 到點時才開始開始畫,用屬性選擇器選到最外層才會讓套件動態添加 class 使動畫觸發,SVG 圖用 AI 轉出來參考參數,這邊動畫實現的方式是讓線段變為虛線,然後範圍設定超大,一開始就會顯示虛線的空白段,接著 transition 變為無虛線來實現畫圖動畫。 ```css= [data-aos="anim-line"] { polygon { fill: none; stroke: #2fc590; stroke-width: 1.3; stroke-miterlimit: 10; stroke-dasharray: 6000; stroke-dashoffset: 6000; transition: 15s; } &.aos-animate { polygon { stroke-dashoffset: 0; } } } ``` --- ### 11.navbar 多級選單的實現方式 手機版本 : 選單已變漢堡,點擊時將選單下拉出現 * 用 JS 監聽點擊時切換 class 改變位置,多添加一個不同定位的 class * 用 label 包住漢堡,透過 checkbox 的 checked 狀態來改變 CSS 實現定位的變換 多級選單 * 透過純 CSS 的 a 、 button 的 :active 來滑出次級 menu * 這次用的方式為將第一層的 li 內放入 次級的 menu 然後再絕對定位到畫面外( relative 設在畫面中的第一層 ul 上 ),以此完成大小相同的次級 menu,使用 JQ 來監聽點擊事件。 ![](https://i.imgur.com/EipMZ48.png) ```javascript= // 選單點擊時去抓到被點擊的下一個元素切換 class // 這邊是用 a 的 padding 去撐開 li 的尺寸,讓整個區塊都能被點擊 // 見上方結構 $('a.trigger').click(function(e){ $(this).next().addClass('go-right') }) // 返回按鍵是抓到返回的 class 後去將上方加入的 class移除 // 每個次級 menu 使用同個 class 也沒關係,因為出來的只有一個 ul,對於其他 ul 等於沒有這個 class 去移除,所以沒差。 $('.back').click(function(e){ $('.menu-second').removeClass('go-right') }) ``` --- ### 12.快速隱藏滾輪 以下請複製貼上 ```css= body::-webkit-scrollbar { /*隱藏滾輪*/ display: none; } ``` --- ### 13.多級選單實作方式-2 **列表甲**內各選項內再包一個**列表乙**,**列表乙**個選項內又再包一個**列表丙**,以此方次一直包下去行程多級選單 ; 要包起來的原因在於 hover 的效果範圍,若不包而定在外部的話會造成 hover 時顯示下一個選單,當滑到下一個選單時整個選單消失的問題 ; 透過當上層選單 hover 時,下層選單 display:none 變為 block 來顯示內容,以此方式即可陸續顯示下層內容。 * 此範例的最後一級為圖片 ![](https://i.imgur.com/b7qQgme.png) --- ### 14.增加工作效率方法a發現 在我寫 SCSS 的時候時常會有重複性的屬性,這時候可做兩種統整方式 1. 例如是不用設定值的屬性就可以將常用的組合寫成 snippet 提升效率 ```json= { "generate random img": { "prefix": "rimg", "body": [ "<img src=\"https://picsum.photos/200/300\" alt=\"lost\">" ], "description": "generate random img" }, "display: flex": { "prefix": "df", "body": [ "display: flex;" ], "description": "display: flex" }, "flex family one": { "prefix": "fcc", "body": [ "display: flex;", "justify-content: center;", "align-items: center;" ], "description": "set child to middle" }, "flex family two": { "prefix": "fbc", "body": [ "display: flex;", "justify-content: space-between;", "align-items: center;" ], "description": "set child to between" } } ``` 2. 要設定值的屬性像是文字設定、重複使用的漸層、色塊直接包成 @mixin 或是提取 class 到最外層在需要時取用 ```css= @mixin bg-gradient { background: linear-gradient( to left, rgba(139, 147, 169, 0) 0%, rgba(139, 147, 169, 0.5) 70% ); } @mixin normal-h2() { position: relative; color: var(--green); font-size: 2rem; font-weight: 300; @include md { font-size: 1.5rem; } &::before { content: ""; position: absolute; left: -100px; top: 17px; width: 45px; height: 2px; background-color: var(--green); @include md { top: 10px; width: 30px; left: -60px; } } } @mixin normal-p { font-size: 1.5rem; line-height: 3rem; font-weight: 300 } ``` --- ### 15.文字隨螢幕自適應縮放 一般文字設定好後要在各個不同斷點改變 font-size 來實作,或是使用單位 rem 在各斷點改變 html 的預設的 font-size ; 那麼以上這些方式在抵達斷點尺寸時都會跳一下變更樣式,儘管加上 transition 也是不會隨時都有變化,後來發現文字的單位還可以是 % 及 vw , 使用 vw 即可實現隨時隨著螢幕視窗大小自適應尺寸了。 1vw 及代表以**當前可視視窗**除以 100 的結果,vw 就意味著此寬度佔據整個畫面的比例。 --- ### 16.class 的命名方式 在有好幾個頁面的切版中非常困擾,尤其是有很多元件可以統一寫的,使用了很多像名詞命名 * box * item * area * row * wrap * list 以上面這些為主又會加上一堆形容詞 * inner-box * large-box * small-box * text-box * text-area * box-left * img-box * pic-area 還有內容限制的命名可以避免,有時候會有多處可共用 * product-list * price-box 有夠沒有邏輯的命名,但有些就算語意化反而單字很難,遇到單字比較多的簡寫後反而要了自己老命 ; 要自己理出一套有結構性的命名,可能是依照內容類型、依照結構層級、共用樣式這些來生出一個命名標準 ; 先去研究網上文章看看 [Allen王 class 命名大法](https://hackmd.io/@ALN/S1FFfzZYu) --- ### 17.可提取的 style 整理 --- ### 18.:not() 選擇器使用時機 遇到重複性排列時,例如 ul li,在推開間距時後最後一個項目也有 margin 的話,會讓原本整個 ul 在父層中沒對齊,利用 :not() 來讓最後一個項目無設定完成整齊的版面。 --- ### 19.子選擇器 > 真滴方便 ```css= ul > li { margin-bottom: 0.5rem; } ``` --- ### 20.rem & em 如何使用? 這個對於 RWD 很有幫助該研究清楚 em = equal to the width of the capital letter M rem : 根據根元素的 font-size 的倍數 em : 根據父元素的 font-size 的倍數 目前預想的使用時機是以 rem 為主,在大範圍的情況下使用 rem ,然後在包在範圍裡面的內容用 em ,這樣的話當我在各個裝置設定的斷點可以透過更改 html 根元素的 font-size 來調整尺寸,並且依照各個內容裡面的 em 來以該父元素的 font-size 依照比例縮放,不過也是會有不適用的時後,屆時再另外調整即可 --- ### 21.上 favicon 請貼上 ```htmlembedded= <link rel="shortcut icon" type="image/x-icon" href="content/img/favicon.svg"/> ``` --- ### 22.他媽的 還好我有用變數 ![](https://i.imgur.com/b8bOiO8.png) --- ### 23.mixin 行數限制 敬請複製、貼上、@include、傳參數 (尚不確定通用性) ```css= @mixin textLimit($number) { overflow: hidden; text-overflow: ellipsis; display: -webkit-box; -webkit-line-clamp: $number; -webkit-box-orient: vertical; } .card_title { font-size: $fzSub1; line-height: 130%; margin-bottom: 12px; @include textLimit(2); } .card_content { font-size: $fzSub3; font-weight: $fw300; line-height: 160%; @include textLimit(3); } ``` --- ### 24.關於設計稿可能會出現的盲點以及切版 發現到很多設計稿的內容都有過大的問題,原因應該是在於一般螢幕都是在 1920 以下,然而在這尺寸之下再去設計 1920 的桌機版稿件的話,在設計時一定是縮在更小的範圍尺寸去做 1920 的內容,所以直接看起來的好像沒問題,但實際上在切版時會發現原先設計的在實際尺寸看時都大了一號。接著就會出現切好的版又要改的靠腰事 這只能盡量使用變數設定來去解決,尚未想到有什麼更好的方式應對這樣子的情況,設計沒 sence 就 GG。 另外,有碰到看起來應該是相同的 component 但是內外距的設定卻又有很多種,這時造成多寫了很多 &.class 來去個別化,以至於整個樣式管理很雜,應該不管這種奇怪的設計,直接統一間距處理,若之後確認要這麼奇怪的樣式設定的話再改,不然浪費時間 --- ### 25.中文字整齊的排版 因為有文字、標點符號、全形半形的問題,所以常常在斷行處(行末)會有一致的留白,可以這樣處理,但英文就不一定合適了,因為會把單字截斷 ```css= .text { text-align: justify; } ``` --- ### 25.神技 - 將有色 icon 轉為白色 原理為將明度降為最低 0 等於黑色再反轉成白色 ```css= .aln_social_links img:hover { filter: brightness(0) invert(1); } ``` --- ### 26.彩帶雨 ```htmlembedded= <div class="wrapper"> <div class="confetti-11"></div> <div class="confetti-10"></div> <div class="confetti-9"></div> <div class="confetti-8"></div> <div class="confetti-7"></div> <div class="confetti-6"></div> <div class="confetti-5"></div> <div class="confetti-4"></div> <div class="confetti-3"></div> <div class="confetti-2"></div> <div class="confetti-1"></div> <div class="confetti-0"></div> </div> ``` ```css= //ribbon animation (SCSS) .wrapper { position: absolute; top: 0; left: 0; width: 100%; min-height: 400vh; z-index: 3; pointer-events: none; } [class|="confetti"] { position: absolute; } $colors: (#d13447, #ffbf00, #263672); @for $i from 0 through 150 { $w: random(8); $l: random(100); .confetti-#{$i} { width: #{$w}px; height: #{$w * 2}px; background-color: nth($colors, random(3)); top: -10%; left: unquote($l + "%"); opacity: random() + 0.5; transform: rotate(#{random() * 760}deg); animation: drop-#{$i} unquote(3 + random() + "s") unquote(random() + "s"); animation-delay: unquote(random() + "s"); } @keyframes drop-#{$i} { 100% { top: 110%; left: unquote($l + random(15) + "%"); } } } ```