<Gallery items='this.data' />
items
變數代替 props.items
,這裡用到 ES6 的 destructuring 語法(我們在 import ReactDOM render function 時也有用過)。const Gallery = (props) => {
const { items } = props;
};
.map()
將資料組合成 list group.<a>
加上 inline-style, React 的 style 值要以 object 的形式寫。const Gallery = (props) => {
const { items } = props;
const el = items.map(item => (
<li key={item.id} className={Style.item}>
<a href="#" style={{ backgroundImage: `url(${item.cover_photo.urls.thumb})` }}>
{item.title}
</a>
</li>));
return <ul>{el}</ul>;
};
前面我們偷懶,給 gallery item 固定的長寬,現在來依照 mockup 製作動態的寬度。
依照 mockup,在手機的尺吋一行會有四個相簿,我們要把瀏覽器的寬減去相簿之間的距離,再減去與左右兩邊的空間,除以一行的相簿數目,就是每個相簿該有的寬度。然後相簿要正方形,不管寬度怎麼變,高度也要跟著變,這些都可以用純CSS做到。
首先來計算寬度,由於還會有「照片」的區域,我們先用一個<div>
包住相簿,並加上gallery
的 class name,增加左右各 8px 的 padding.
相簿間距也是8px,所以是.gallery
的總寬度減去三倍的8px再除以四,就是每個相簿該有的寬度。
再加上 padding-bottom 增加與下方的距離。
.gallery {
margin: 0 8px;
}
.item {
display: inline-block;
width: calc((100% - 8px * 3)/4);
margin-bottom: 8px;
}
接下來做相簿的高度,這邊用到一個原則「padding 百分比單位是由元素的寬度決定」,也就是說當元素任一邊padding為100%時,其長度和元素的寬度是一樣的,例如元素寬度是100px,padding-bottom: 100%
也就等於padding-bottom:100px
.
有了這個知識就能製作等比例縮放的方形,重點是在<li>
裡面的<a>
高度為0, padding-bottom:100%
。寬度100%和父元素一樣。
.item a {
font-size: 0;
display: block;
width: 100%;
height: 0;
padding-bottom: 100%;
overflow: hidden;
background-repeat: no-repeat;
background-position: center center;
background-size: cover;
}
最後來讓相簿水平排例,以往的做法會使用 float,這一次我們來用用 flexbox。
在<ul>
新增 className={Style['list-group']}
, 並在app.css
裡加入
.list-group {
display: flex;
flex-wrap: wrap;
justify-content: space-between;
}
JSX裡不能有 hyphen 出現,如果class name有hyphen的話,就要用['class-name']
的寫法,不能用 dot selector。
現在最後一行有了問題,如果不是剛好四個的話,相簿間距也會平均分配,如果在 flex-container 加入一個具有 flex 屬性的空白偽元素,能適時將多餘的空間填滿,但是最後一行相簿之間空隙也會消失。
.list-group:after {
content: '';
flex: auto;
}
解決方法是使用 CSS nth-child(an+b)
與nth-last-child(an+b)
的組合技。讓最後一行多出左邊的margin。下面這段選擇語法意思是說「第1, 5, 9,... 個子元素,同時也是倒數第4,3,2,1個子元素,它之後同階層的元素,都加上margin-left:8px
」。這邊的交集也只有第9個相簿符合,於是第10, 11, 12 個相簿會多出左邊margin。
.list-group .item:nth-child(4n+1):nth-last-child(-n+4) ~ .item {
margin-left: 8px;
}
然後再使用 media query 加上其他螢幕大小的設定,自動化 gallery layout 就完成了!