我在React裡面撰寫CSS常用的工具是styled-components,一般來說,CSS的限制是他沒有變量、循環和函數等邏輯,所以我們很難在撰寫純CSS的時候做出複雜的變化,為了解決這個問題,開始出現了在JS上編寫CSS的做法, styled-components 是其中一種解決方案。
使用styled-components的好處有很多,例如它可以幫助我們將樣式寫成更具語義化的組件的形式,提高可讀性。另外有一個我很喜歡的功能,就是可以將React的參數用props的方式傳入來控制樣式,所以頁面的樣式就能夠透過改變這些參數來做更隨心所欲的變化,這兩個部分在今天這個單元都會使用到。
而且因為CSS的作用域是全局的,所以很容易產生衝突,特別是在專案更複雜的時候。但是使用styled-components會為我們生成的React元件產生隨機的className,重複使用這些元件的時候隨機的className也會不同,因此能夠避免元件之間className的衝突,順利的解決CSS全局作用域的問題。
styled-components
CSS Evolution: From CSS, SASS, BEM, CSS Modules to Styled Components
Styled Components:讓樣式也成為組件
在 Day03 準備好資料之後,我們要開始規劃一下我們的頁面,下面這個圖是我想像當中的頁面雛形。
為了讓想像不再是想像,而是能變成實體,我先開始做出整個程式的骨幹。
我延用create-react-app他原本的App.js來當作背景,並包覆<TicTacToe />
元件
為了方便呈現,我先給了每個元件border屬性
為了要做出想像圖的layout,我會喜歡用grid和flex這兩個CSS的屬性。
深入解析 CSS Flexbox
圖解:CSS Flex 屬性一點也不難
CSS Grid 屬性介紹
CSS Grid For Everyone
Grid Garden - A game for learning CSS grid
上面 CSS Grid For Everyone 這位講者,Part1和Part2講的內容我覺得還蠻清楚的,幫我釐清很多問題,讓我覺得使用grid和flex這兩個屬性不用再那麼害怕,然後講解過程中也會提到一些實務經驗,我覺得很受用,所以推薦給大家。
另外Grid Garden是透過闖關遊戲的方式來熟悉grid的語法,還蠻有趣的,也推薦給大家。
不過在使用這兩個屬性的時候還是需要考慮一下瀏覽器支援度,目前grid還不到90%,所以在使用的時候還是要特別留意。
在簡單的調整排版之後,我們的成果如下:
大致上整個layout的佈局已經被我們安排定位了,簡單分享一下我的作法,包覆元件的div tag我把它設為滿版成為背景,
.App {
background: #ffd85c;
width: 100%;
min-height: 100vh;
display: flex;
justify-content: center;
}
並且我將它宣告成display: flex,讓他成為flex的外部容器,如此一來,在外部容器就能夠使用justify-content來使內部的元件水平置中。
在設定棋盤大小及獲勝條件大小的參數設定區塊,我用一個div使他成為grid的外部容器,並且在外部容器設定grid-template使內部元件能夠以2x2的方式排列。
接著裡面的棋盤格子區塊我也想要用grid來處理,首先,我們需要根據我們 Day03 設計的兩個參數,gameScale以及blocks來將棋盤畫出來。
透過map方法的迭代,我們可以產生九個div tag(因為我們預設是3x3的棋盤)。接著,為了使用grid來產生3x3的棋盤,我將gameScale參數當成props傳入這個styled-component的元件中,將包住這九個div的外部容器設為display: grid,並且根據gameScale來決定grid-template的columns以及rows,另外,grid還有一個很方便的屬性,就是我們不用再透過margin或是padding的方式來設定方格的上下間距,而是能夠過grid-gap
來設定方格間的距離。
最後,由於考量到我們是伸縮自如的棋盤,在棋盤區域大小是固定的狀況下,gameScale變大的時候,相對每一個block就會變小,但是如果在此時方格的間距是定值的話,方格的大小和間距的寬度很會不成比例,所以這邊間距我們會讓gameScale與間距成反比,因此當gameScale越大,block會越小,同時間距也會跟著變小。
透過grid排列完棋盤之後,在對每一個block做一點樣式調整,就會變成下圖模樣。如果在這時候我們手動修改gameScale的預設值的話,我們也可以順利的把它變成4x4或是5x5的棋盤。
到這邊我們就有一個基本的雛形了!下一篇我們會開始透過事件處理,讓我們可以順利的在棋盤上下棋!