綱要
同學們應該發現了最近課堂上出現了gulp watch
時,node-sass要你更新depth 2的套件訊息,我們雖然可以照著錯誤訊息上的指示更新 node 相依套件或者跑一次npm audit fix
。
接著你會看見 Git 突然顯示了packge-lock.json
和packge.json
兩隻檔案的變更(有時只會更新lock那隻),而你在修正了相依套件更新的問題後必須要將這個變更Push到Git上。
假如跟你同個專案的其他工程師更新了這些檔案,卻忘了或不知道更新的內容包含packge-lock.json
和packge.json
,那麼啟動環境時就會顯示缺漏特定模組的錯誤訊息、環境也跑不起來。或者更慘的狀況是環境能跑、功能卻無法顯示或不正常,而你們對外Release了產品新版本後才發現…XD
正確的觀念是,只要Git上的專案有任何新的變更,在你Fast-forward-merge
或者直接將目標分支merge
到自己的分支上時,一定要記得跑一次npm install
來避免這樣的問題,千萬不要因為沒更新 Package 就略過這個步驟。
還記得剛開始這個專案時我們做過的npm init
初始化得到的package.json
嗎?
後頭為了gulp任務管理工具我們又安裝了其他相依套件:
通常我們不會把node_modules
這麼肥大的檔案直接丟上Git,而是依賴package.json
和package-lock.json
中已安裝套件的記錄,透過npm install
這個指令重新安裝回來,同專案的同事也可以利用這份json來讓開發環境同步,也可以將各套件的版號刪除上箭號「^」來鎖定版本。
以前我們都學過Media Query媒體查詢來做 RWD Breakpoint 判別特定寬度下 UI 要怎麼變化,而在Sass/Scss中,定義的方式會稍稍有些不同:
$ipad_landscape: "screen and (max-width: 1024px) and (orientation: landscape) and (min-device-pixel-ratio: 2)";
@mixin ipad_landscape {
@media #{$ipad_landscape} {
@content;
}
}
.block {
background-color: #f90;
@include ipad_landscape {
background-color: #333;
}
}
/* 編譯後的CSS */
.block {
background-color: #f90;
}
@media screen and (max-width: 1024px) and (orientation: landscape) and (min-device-pixel-ratio: 2) {
.block {
background-color: #333;
}
}
還記得2/8上課時我們提到:你不應該把時間花在命名容器上,那是下等人做的事情
而且將html的結構以組件的概念依照需求來做排列,為了達到這個理想的目的,今天起大約兩週時間就需要建構我們自己的 Code Library,結訓作業會派得上用場,之後也能整併到自己的公司專案裡馬上使用喔!
可以參考老師的Github範例來配置:
style.scss
/* 注意引用的順序喔 */
@import "_reset.scss";
@import "_variable.scss";
// @import "_commonStyle.scss"; 這隻將會抽離,各位用不到
@import "_flexbox.scss";
@import "_dataAttribute.scss";
@import "_mediaQueries.scss";
html {
touch-action: manipulation;
height: 100%;
body {
font-family: "Microsoft JhengHei", "Helvetica Neue", Helvetica, Arial, sans-serif;
touch-action: manipulation;
height: 100%;
}
}
_reset.scss
重設瀏覽器規則,跨裝置跨瀏覽器的必備作業。
html, body, div, section, aside, figure, span, applet, object, iframe,
h1, h2, h3, h4, h5, h6, p, blockquote, pre,
a, abbr, acronym, address, big, cite, code,
del, dfn, em, font, img, ins, kbd, q, s, samp,
small, strong, sub, sup, tt, var,
b, u, i, center,
dl, dt, dd, ol, ul, li,
fieldset, form, label, legend,
table, caption, tbody, tfoot, thead, tr, th, td {
margin: 0;
padding: 0;
border: 0;
outline: 0;
font-size: 100%;
vertical-align: baseline;
background: transparent;
text-decoration: none;
}
body {
line-height: 1;
}
ol, ul {
list-style: none;
}
blockquote, q {
quotes: none;
}
blockquote:before, blockquote:after,
q:before, q:after {
content: '';
content: none;
}
/* remember to define focus styles! */
:focus {
outline: 0;
}
/* remember to highlight inserts somehow! */
ins {
text-decoration: none;
}
del {
text-decoration: line-through;
}
/* tables still need 'cellspacing="0"' in the markup */
table {
border-collapse: collapse;
border-spacing: 0;
}
.clearfix {
*zoom: 1;
}
.clearfix:before, .clearfix:after {
display: block;
content: "";
line-height: 0;
}
.clearfix:after {
clear: both;
}
_variable.scss
我們通常會將Sketch或者Figma專案上的色票設定、狀態樣式存放在這支檔案。
命名好的變數就可以直接在其他scss檔案上調用,當你有多樣板的需求(聖誕節、春節主題等)就可以非常彈性的擴充你的專案外觀。
$h1FontSize: 1.85rem;
$white: #fff;
$darkGray: #37424C;
$dark: #37424C;
$red: #dc222a;
$blue: #2287DC;
$green: #1fc66b;
$lightGreen: #36f88d;
$defaultGray: #999;
$landGray: #C9CCCF;
$lightGray: #EEEFEF;
$riceWhite: #f9f9f9;
$gray: #d9d9d9;
$carrotOrange: #eb7428;
$manatee: #92989E;
$bgColor_lv1: linear-gradient(to right, #EB7428, #DC222A);
$bgColor_lv2: #1B2733;
//screen
$wideScreen: "only screen and(min-width: 1920px) and (min-height: 1024px) and (orientation: landscape)";
$largeScreen: "only screen and(max-width: 1920px) and(min-width: 1680px) and (max-height: 1080px) and (min-height: 1050px) and (orientation: landscape)";
flexBox.scss
本次課程的重點就是這隻排版邏輯,我們會定義出flexbox
在row或column不同邏輯下的排列規則外,還會設置指定每行顯示N個元素為的規則,真正幫助你節省切版時間之外也保持更好的維護性。
@mixin boxSizing {
box-sizing: border-box;
}
@mixin flexBox($direction, $alignItems, $justifyContent) {
display: flex;
flex-direction: $direction;
align-items: $alignItems;
justify-content: $justifyContent;
}
/* 指定一行顯示幾個元素,element UI採24分、Bootstrap則是12分,這裡用element UI */
@mixin dataRowCount {
@for $i from 1 through 24 {
[data-row-count="#{$i}"] {
.data_row {
width: calc(100% / #{$i});
}
}
}
}
@for $i from 1 through 24 {
[data-row-count="#{$i}"] {
.data_row {
// 使用計算屬性來切割寬度
width: calc(100% / #{$i});
}
}
}
/* 注意,假如你的專案有套用Boostrap的話,這裡的row請替換成別的名稱,會撞名 */
.row {
@include boxSizing;
position: relative;
width: 100%;
margin: 0;
@include dataRowCount;
&.full {
width: 100%;
height: 100%;
}
&.horizontal {
@include flexBox(row);
&.v_center {
@include flexAlign(center, flex-start);
}
&.h_center {
@include flexAlign(flex-start, center);
}
&.end {
@include flexAlign(center, flex-end);
}
&.bottom {
@include flexAlign(flex-end, center);
}
&.bottom_left {
@include flexAlign(flex-end, flex-start);
}
&.bottom_right {
@include flexAlign(flex-end, flex-end);
}
&.space {
justify-content: space-between;
}
}
&.vertical {
@include flexBox(column);
&.v_center {
@include flexAlign(flex-start, center);
}
&.h_center {
@include flexAlign(center, flex-start);
}
&.end_right {
@include flexAlign(flex-end, flex-end);
}
&.end_left {
@include flexAlign(flex-end, flex-start);
}
&.end {
@include flexAlign(flex-end, center);
}
}
&.normal {
@include flexAlign(flex-start, flex-start);
}
&.center {
@include flexAlign(center, center);
}
&.half {
width: 50%;
}
&.wrap {
flex-wrap: wrap;
}
&.space {
justify-content: space-between;
}
&.inset {
@include boxSizing;
padding: 1rem;
}
&.static {
/* 如果你不想被row中的width: 100%影響,加上這個屬性 */
width: auto;
}
}
_dataAttribute.scss
將它放置在_flexBox.scss
後載入的理由就是為了要覆寫原先的樣式,我們不喜歡直接去改已經寫好的mixin
,所以這個方式雖然只是在html上增加些參數,卻能很彈性的處理像是margin、border、border-radius之類需要因應狀況來給值的外觀。
[data-space="space-next"] {
margin-right: 1rem;
}
@for $i from 1 through 10 {
[data-space-next='#{$i * 0.1 + "rem"}'] {
margin-right: #{$i * 0.1 + "rem"};
}
}
// html ex: data-space-next='0.5rem'
@each $direction in "next", "before", "vertical", "horizontal", "bottom" {
@for $i from 0 through 10 {
[data-space-#{$direction}="#{$i * 0.1 + "rem"}"] {
@if $direction == "next" {
margin-right: #{$i * 0.1 + "rem"};
}
@if $direction == "before" {
margin-left: #{$i * 0.1 + "rem"};
}
@if $direction == "vertical" {
margin: #{$i * 0.1 + "rem"} 0;
}
@if $direction == "horizontal" {
margin: 0 #{$i * 0.1 + "rem"};
}
@if $direction == "bottom" {
margin-bottom: #{$i * 0.1 + "rem"};
}
}
}
}
// 百分比的寫法
@each $direction in "next", "before", "vertical", "horizontal", "bottom" {
// 20最後會是2%,所以同學們可以自己依照需要來改寫
@for $i from 0 through 20 {
[data-space-#{$direction}-percent="#{$i * 0.1 + "%"}"] {
@if $direction == "next" {
margin-right: #{$i * 0.1 + "%"};
}
@if $direction == "before" {
margin-left: #{$i * 0.1 + "%"};
}
@if $direction == "vertical" {
margin: #{$i * 0.1 + "%"} 0;
}
@if $direction == "horizontal" {
margin: 0 #{$i * 0.1 + "%"};
}
@if $direction == "bottom" {
margin-bottom: #{$i * 0.1 + "%"};
}
}
}
}
//space direction
[data-space="space-before"] {
margin-left: 1rem;
}
[data-space="space-vertical"] {
margin: 1rem 0;
}
[data-space="space-horizontal"] {
margin: 0 1rem;
}
[data-space="space-top"] {
margin-top: 1rem;
}
[data-space="space-bottom"] {
margin-bottom: 1rem;
}
[data-space="padding-xs"] {
padding: 0.5rem;
}
[data-width="column-name"] {
width: 10rem;
line-height: 1.3;
}
@for $i from 1 through 50 {
[data-v-space="#{$i * 0.1 + "rem"}"] {
padding: #{$i * 0.1 + "rem"} 0;
}
}
@for $i from 1 through 50 {
@each $direction in "top", "left", "right", "bottom" {
[data-space-#{$direction}="#{$i * 0.1 + "rem"}"] {
padding#{"-" + $direction}: #{$i * 0.1 + "rem"};
}
}
}
//border
[data-border="left"] {
border-left: 1px solid $lightGray;
}
@each $direction in "top", "left", "right", "bottom" {
[data-border="#{$direction}"] {
#{"border-" + $direction}: 1px solid $lightGray;
}
}
[data-border="left"]:first-child {
border-left: none;
}
[data-border="bottom"] {
border-bottom: 1px solid $lightGray;
}
[data-border="bottom"]:last-child {
border-bottom: none;
}
[data-border="horizontal"] {
border-left: 1px solid $lightGray;
border-right: 1px solid $lightGray;
}
//
@each $clearList in "top", "left", "right", "bottom" {
[data-border-clear="#{$clearList}"] {
#{"border-" + $clearList}: none;
}
}
[data-border="none"] {
border: none;
}
// text-align
@each $fontAlign in left, right, center {
[data-font-align="#{$fontAlign}"] {
text-align: $fontAlign;
}
}
@each $fontSize in "default", "small", "xs", "large", "xl" {
[data-font-size="#{$fontSize}"] {
@if $fontSize == "default" {
font-size: 1rem;
}
@if $fontSize == "small" {
font-size: 0.85rem;
}
@if $fontSize == "xs" {
font-size: 0.6rem;
}
@if $fontSize == "large" {
font-size: 1.2rem;
}
@if $fontSize == "xl" {
font-size: 2rem;
}
}
}
[data-font-size="default"] {
font-size: 1rem;
}
//font color
@each $color in "red", "blue", "carrot-orange" {
[data-color="#{$color}"] {
color: #{$color};
@if $color == "carrot-orange" {
color: #{$carrotOrange};
}
}
}
//max and min-width
@each $maxWidth in "xs", "small", "default", "medium", "large", "xl" {
[data-max-width="#{$maxWidth}"] {
@if $maxWidth == "xs" {
max-width: 80px;
}
@if $maxWidth == "small" {
max-width: 120px;
}
@if $maxWidth == "default" {
max-width: 160px;
}
@if $maxWidth == "medium" {
max-width: 200px;
}
@if $maxWidth == "large" {
max-width: 300px;
}
@if $maxWidth == "xl" {
max-width: 500px;
}
}
}
//width percentage
@for $i from 0 through 100 {
[data-width='#{$i + "%"}'] {
width: #{$i + "%"};
}
}
//width rem
@for $i from 1 through 100 {
[data-width='#{$i + "rem"}'] {
width: #{$i + "rem"};
}
}
//width size prefix
@each $size in "small", "default", "large", "xl" {
[data-width='#{$size}'] {
@if $size == "small" {
width: 320px;
}
@if $size == "default" {
width: 768px;
}
@if $size == "large" {
width: 800px;
}
@if $size == "xl" {
width: 1000px;
}
}
}
//height
@for $i from 1 through 100 {
[data-height="#{$i}vh"] {
height: #{$i}vh;
}
}
//data-inset float
@for $i from 0 through 20 {
[data-inset="#{$i * 0.1}rem"] {
padding: #{$i * 0.1}rem;
}
}
//data-flex
@for $i from 0 through 24 {
[data-flex="#{$i}"] {
flex: #{$i};
}
}
//input adjust
@each $dataAttr in "default", "full", "short", "common-count", "keywords", "long-string", "date", "caption", "search", "xs" {
[data-style="#{$dataAttr}"] {
@if $dataAttr == "default" {
width: 8rem;
}
@if $dataAttr == "common-count" {
width: 10rem;
margin-right: 10px;
}
@if $dataAttr == "long-string" {
width: 20rem;
}
@if $dataAttr == "short" {
width: 6.5rem;
}
@if $dataAttr == "full" {
width: 100%;
}
@if $dataAttr == "date" {
width: 100%;
margin: 0;
padding-right: 26px;
}
@if $dataAttr == "caption" {
width: 100%;
margin: 0;
border-right: none;
border-top-left-radius: 6px;
border-top-right-radius: 0;
border-bottom-left-radius: 6px;
border-bottom-right-radius: 0;
}
@if $dataAttr == "search" {
width: 100%;
margin: 0;
padding-right: 26px;
}
@if $dataAttr == "xs" {
width: 3rem;
}
}
}
假如你都配置好了這些樣式,以後對於基本的flexbox排列規則就能更容易上手!
<div class="row horizontal wrap" data-row-count="3" data-width="50%">
<!--另外再用其他樣式設定data_row的高度和外觀就行了-->
<div class="data_row"></div>
<div class="data_row"></div>
<div class="data_row"></div>
<div class="data_row"></div>
<div class="data_row"></div>
<div class="data_row"></div>
</div>
別忘了這週開始會有回家作業,每一次上課雖然課堂會有一些練習時間,但其實真正要把東西學進骨子裡,還是需要有一個標的來臨摹會比較好。
這次的回家作業是RWD手機版面,題目可以看這裡:回家作業題目
Scss
flexbox
data-attribute
綱要:
Feb 9, 2025一個方便大家快速上手使用的Scss庫。 如果你偏好Scss開發,且需要和UI/UX設計師按照Guideline協作,這份Library很適合你使用! 當然,你也能很輕鬆的擴充和維護這個架構! :::warning 特別注意!從 Sass 2.0 版本開始會有一些Breaking Change map-get 日後請改用 map.get() 除法不再使用 slash 符號 '/',請改用math.div() :::
Oct 30, 2024🚀 Vue 3 網頁應用秒變行動 APP,你相信嗎?是不是覺得製作 APP 很複雜、門檻很高?😵💫 別擔心,現在只要你會寫 Vue 3 網頁應用,就可以用 Capacitor 簡單地將它打包成原生 Android 或 iOS 的行動 APP!🎉
Sep 28, 2024綱要:
Aug 14, 2024or
By clicking below, you agree to our terms of service.
New to HackMD? Sign up