Flexbox 實作
預期結果
每一塊Panel為直向排列,由左往右。Panel中共有三段文字,點擊後會各自從上下彈入!
功能拆解
- flexbox
Flexbox
講師的另一套flexbox課程
排版目前的大宗屬Flex莫屬,像是box model的進階版,有外容器和內元件之分。
CSS Flexible Box Layout is a module of CSS that defines a CSS box model optimized for user interface design, and the layout of items in one dimension.
簡單來說:
利用display屬性,將父元素設定成flex
or inline-flex
來建立一個flex container,同時子元素會成為flex items。
-
Flex container
- flex-direction (改變影響排列的軸線)
- row/ row-reverse
- column/ column-reverse
- row為default
- flex-wrap (超出範圍時,是否換行)
- nowrap為default
- wrap
- flex-flow (flex-direction和flex-wrap縮寫)
- ex: flex-flow: row wrap;
- flex-direction (改變影響排列的軸線)
遙想…..以前”被搞弄昏”左右上下置中 bla bla
對齊系列 (一樣也是設定在flex container上,根據軸線方向會不同)
- justify-content (水平方向的對齊)
- flex-start
- flex-end
- center
- space-between (左右不留白)
- space-around( 左右會留白)
- align-items (垂直方向的對齊)
- flex-start
- flex-end置底
- center置中
- stretch撐滿
- baseline
- align-content (多行版本)
- flex-start
- flex-end
- center
- space-between
- space-around
- stretch
以上是flex container相關屬性的設定,接下來是關於flex item的屬性
- flex
- flex-grow, flex-shrink, flex-basis的縮寫
- flex-grow
- 為item的伸展性,預設值為0,即不縮放!
- 當還有剩餘空間時,item放大比例
- flex-shrink
- 為item的收縮性,預設值為1
- 當空間不足時,item縮小比例
- flex-basis
- 設定item的初始長度/寬度
p.s.跟著青蛙學flexbox的遊戲 & 砲台遊戲,可以慢慢練一點感覺
回到主題….
還沒改之前練習長這樣
block會照預設的flow由上至下排列很正常
Step1
觀察html結構
<div class="panels">
<div class="panel panel1">
<p>Hey</p>
<p>Let's</p>
<p>Dance</p>
</div>
<div class="panel panel2">
<p>Give</p>
<p>Take</p>
<p>Receive</p>
</div>
<div class="panel panel3">
<p>Experience</p>
<p>It</p>
<p>Today</p>
</div>
<div class="panel panel4">
<p>Give</p>
<p>All</p>
<p>You can</p>
</div>
<div class="panel panel5">
<p>Life</p>
<p>In</p>
<p>Motion</p>
</div>
</div>
**panels 包含5個panel,每個panel包含3個p tag **
在panels設定display:flex
,因預設為row,panel變成縱向由左往右排列
在panel設定flex:1
,排完item還有剩餘空間時,item的伸展比
Step2
接下來目標是處理每個panel中的文字排列
panel在這個步驟成為了flex container,要控制子元素p的排列
在panel設定dispaly:flex
,且設定項目水平&垂直方向都置中,justify-content:center
&align-items:center
以及用列方式垂直排列flex-direction:column
Step3
現在每個panel中的p tag,都集中在中間。要讓他可以充分利用剩餘的空間。
panel 下所有的p tag使用flex:1 0 auto
,等於…..
- flex-grow:1 ,item
p
空間有剩時,要撐滿空間,大家很公平1:1:1 - flex-shrink:0 ,空間不足時,不縮小
- flex-basis:auto,預設分配的空間
/* Flex Items */
.panel > * {
/* 省略 */
flex: 1 0 auto;
display: flex;
justify-content: center;
align-items: center;
}
p.s.怎麼有點混亂…..發現把panel設定justify-content:space-around
好像也可以達到一樣效果(?)
發現排列對齊方式,會影響Step 4計算文字translate的%不同
Step4
處理點擊發生時,上下行文字的彈入動畫&panel的占比伸展
.panel>*:first-child {
transform: translateY(-100%);
}
.panel.open-active>*:first-child {
transform: translateY(0);
}
.panel>*:last-child {
transform: translateY(100%);
}
.panel.open-active>*:last-child {
transform: translateY(0);
}
寫一個class,供panel被打開時套用,佔比變大外也同時改變font-size
.panel.open {
flex: 5;
font-size: 40px;
}
測試套用class,預覽效果~
Step5
進入到script的部分
又可以再細分成:
- 點擊圖片時,觸發panel打開的transition (add class “open”)
- transition結束時,再觸發文字動畫 (add class “open-active”)
注:transition end時會有兩個transition event
script result:
const panels = document.querySelectorAll('.panel');
function toggleOpen() {
this.classList.toggle('open');
}
function toggleActive(e) {
if (e.propertyName.includes('flex')) {
this.classList.toggle('open-active');
}
}
panels.forEach(panel => panel.addEventListener('click', toggleOpen));
panels.forEach(panel => panel.addEventListener('transitionend', toggleActive))