
先日制作した案件で、タイムライン(過去→未来)があったんですね。
こういうのです。

デザインがイラレで来ていて、さてどうしましょうか、と。
もちろん画像でもOKなんですが、横長をタイムラインをスマホで見たら小さくて見えない。
かといって縦長の画像は作りたくない。※それなりに数があったので。
それじゃCSSだけで実装しましょ、とういうことになりました。
【DEMO】
やってみよう
条件
- 広い画面では横型、狭くなったら縦型にする
- 項目数は変動する
- ポイントごとに目印をつける
もちろん、まず一直線を引いて、その上に絶対配置でポイントを打つのもアリだと思います。
今回は基本形を元にちょっといろいろしてみました。
けどあんまりうまくいかなかった。。。
ついでにCSSがいろいろ汚染しまくって悪い見本みたいになってます。
お目汚しですが、よかったらどうぞ。。。
基本形
HTML
<div class="timeline">
<div class="timeline-item">
<p class="timeline-label">10年前</p>
<p class="timeline-content">じつはまだ学生でした。</p>
</div>
<div class="timeline-item now">
<p class="timeline-label">現在</p>
<p class="timeline-content">結構いい年です。</p>
</div>
<div class="timeline-item">
<p class="timeline-label">10年後</p>
<p class="timeline-content">Webはまだ大丈夫。</p>
</div>
<div class="timeline-item">
<p class="timeline-label">20年後</p>
<p class="timeline-content">スナフキンになりたい。</p>
</div>
<div class="timeline-item">
<p class="timeline-label">その後</p>
<p class="timeline-content">仙人。</p>
</div>
</div>
SASS
.timeline{
padding: 3rem 5rem;
background-color: #f0f0f0;
&-item{
position: relative;
border-left: 1px solid #000;
padding: 0 0 30px 30px;
&:before{
content: '';
display: block;
width: 10px;
height: 10px;
position: absolute;
left: 0;
top: 0;
border-radius: 100%;
background-color: #000;
transform: translateX(-50%) translateY(-50%);
}
&:last-of-type{
padding-bottom: 0;
&:before{
width: 0;
height: 0;
border-style: solid;
border-width: 10px 5px 0 5px;
border-color: #000000 transparent transparent transparent;
border-radius: 0;
background-color: transparent;
top: auto;
bottom: 0;
transform: translateX(-50%) translateY(0);
}
}
}
@media(min-width : 768px){
display: table;
table-layout: fixed;
width: 100%;
&-item{
display: table-cell;
vertical-align: top;
padding: 0;
border:{
top: 1px solid #000;
bottom: 0;
left: 0;
}
&:last-of-type{
padding-bottom: 0;
text-align: right;
&:before{
border-width: 5px 0 5px 10px;
border-color: transparent transparent transparent #000000;
top: 0;
right: 0;
bottom: auto;
left: auto;
transform: translateX(0) translateY(-50%);
}
p{
text-align: left;
}
}
}
&-label,
&-content{
transform: translateX(-50%);
text-align: left;
display: block;
max-width: 70%;
}
&-label{
text-align: center;
position: absolute;
top: 0;
left: 0;
transform: translateX(-50%) translateY(-120%);
}
&-content{
margin-top: 10px;
}
&-item:last-of-type &-label,
&-item:last-of-type &-content{
transform: translateX(50%);
text-align: left;
display: inline-block;
max-width: 70%;
}
&-item:last-of-type &-label{
left: auto;
right: 0;
transform: translateX(50%) translateY(-120%);
}
}
}
/* 現在地 */
.timeline-item.now:before{
background-color: #f00;
}
やってること
そんなに難しいことはしてません。
displayを切り替えて、ボーダー引く場所を変えているだけです。
狭い画面では縦型なのでdisplay: block;でいいですね。ボーダーは左に引きました。
横型の場合は、親要素をtableに、子要素をtable-cellにしてみました。(※flexでもうまくいくかもしれません。)
それから親要素にtablelayout: fixed;を指定して均等に割ります。
文字や時間の長さに長短がある場合は子要素のwidthをパーセントで指定してあげればOKです。
目印は子要素の擬似要素で。
基本的には左上に絶対配置して、自分の大きさ分だけ移動(transform: translateX(-50%) translateY(-50%);)します。
最後の子要素だけは矢印っぽくしたいので、三角にしました。これは縦横で向きを変えてあげてくださいね。
現在地は専用のクラスを振って文字色を変えました。
【DEMO】にのっけた他のやつのコードも一応載せときますね。
本当は背景を矢印っぽくするところまで行きたかったんですけど、パッと思いつかなかったので、とりあえず今回はここまで。
年末進行でお忙しいと思いますが、みなさんお体に気をつけて頑張っていきましょう!
HTML
<h2>基本形</h2>
<div class="timeline">
<div class="timeline-item">
<p class="timeline-label">10年前</p>
<p class="timeline-content">じつはまだ学生でした。</p>
</div>
<div class="timeline-item now">
<p class="timeline-label">現在</p>
<p class="timeline-content">結構いい年です。</p>
</div>
<div class="timeline-item">
<p class="timeline-label">10年後</p>
<p class="timeline-content">Webはまだ大丈夫。</p>
</div>
<div class="timeline-item">
<p class="timeline-label">20年後</p>
<p class="timeline-content">スナフキンになりたい。</p>
</div>
<div class="timeline-item">
<p class="timeline-label">その後</p>
<p class="timeline-content">仙人。</p>
</div>
</div>
<h2>数が減っても大丈夫</h2>
<div class="timeline">
<div class="timeline-item">
<p class="timeline-label">10年前</p>
<p class="timeline-content">じつはまだ学生でした。</p>
</div>
<div class="timeline-item now">
<p class="timeline-label">現在</p>
<p class="timeline-content">結構いい年です。</p>
</div>
<div class="timeline-item">
<p class="timeline-label">30年後</p>
<p class="timeline-content">煙になりたい。</p>
</div>
<div class="timeline-item">
<p class="timeline-label">その後</p>
<p class="timeline-content">仙人。</p>
</div>
</div>
<h2>数が増えても大丈夫</h2>
<div class="timeline">
<div class="timeline-item">
<p class="timeline-label">10年前</p>
<p class="timeline-content">じつはまだ学生でした。</p>
</div>
<div class="timeline-item now">
<p class="timeline-label">現在</p>
<p class="timeline-content">結構いい年です。</p>
</div>
<div class="timeline-item">
<p class="timeline-label">10年後</p>
<p class="timeline-content">Webはまだ大丈夫。</p>
</div>
<div class="timeline-item">
<p class="timeline-label">20年後</p>
<p class="timeline-content">スナフキンになりたい。</p>
</div>
<div class="timeline-item">
<p class="timeline-label">30年後</p>
<p class="timeline-content">煙になりたい。</p>
</div>
<div class="timeline-item">
<p class="timeline-label">その後</p>
<p class="timeline-content">仙人。</p>
</div>
</div>
<h2>ボーダー有り</h2>
<div class="timeline border-dashed">
<div class="timeline-item">
<p class="timeline-label">10年前</p>
<p class="timeline-content">じつはまだ学生でした。</p>
</div>
<div class="timeline-item now">
<p class="timeline-label">現在</p>
<p class="timeline-content">結構いい年です。</p>
</div>
<div class="timeline-item">
<p class="timeline-label">10年後</p>
<p class="timeline-content">Webはまだ大丈夫。</p>
</div>
<div class="timeline-item">
<p class="timeline-label">20年後</p>
<p class="timeline-content">スナフキンになりたい。</p>
</div>
<div class="timeline-item">
<p class="timeline-label">その後</p>
<p class="timeline-content">仙人。</p>
</div>
</div>
<h2>ストライプ背景</h2>
<div class="timeline bg-stripe">
<div class="timeline-item">
<p class="timeline-label">10年前</p>
<p class="timeline-content">じつはまだ学生でした。</p>
</div>
<div class="timeline-item now">
<p class="timeline-label">現在</p>
<p class="timeline-content">結構いい年です。</p>
</div>
<div class="timeline-item">
<p class="timeline-label">10年後</p>
<p class="timeline-content">Webはまだ大丈夫。</p>
</div>
<div class="timeline-item">
<p class="timeline-label">20年後</p>
<p class="timeline-content">スナフキンになりたい。</p>
</div>
<div class="timeline-item">
<p class="timeline-label">その後</p>
<p class="timeline-content">仙人。</p>
</div>
</div>
<h2>ストライプ背景</h2>
<div class="timeline-wrapper">
<div class="timeline bg-arrow">
<div class="timeline-item">
<p class="timeline-label">10年前</p>
<p class="timeline-content">じつはまだ学生でした。</p>
</div>
<div class="timeline-item now">
<p class="timeline-label">現在</p>
<p class="timeline-content">結構いい年です。</p>
</div>
<div class="timeline-item">
<p class="timeline-label">10年後</p>
<p class="timeline-content">Webはまだ大丈夫。</p>
</div>
<div class="timeline-item">
<p class="timeline-label">20年後</p>
<p class="timeline-content">スナフキンになりたい。</p>
</div>
<div class="timeline-item">
<p class="timeline-label">その後</p>
<p class="timeline-content">仙人。</p>
</div>
</div>
</div>
SASS
.timeline{
padding: 3rem 5rem;
background-color: #f0f0f0;
&-item{
position: relative;
border-left: 1px solid #000;
padding: 0 0 30px 30px;
&:before{
content: '';
display: block;
width: 10px;
height: 10px;
position: absolute;
left: 0;
top: 0;
border-radius: 100%;
background-color: #000;
transform: translateX(-50%) translateY(-50%);
}
&:last-of-type{
padding-bottom: 0;
&:before{
width: 0;
height: 0;
border-style: solid;
border-width: 10px 5px 0 5px;
border-color: #000000 transparent transparent transparent;
border-radius: 0;
background-color: transparent;
top: auto;
bottom: 0;
transform: translateX(-50%) translateY(0);
}
}
}
@media(min-width : 768px){
display: table;
table-layout: fixed;
width: 100%;
&-item{
display: table-cell;
vertical-align: top;
padding: 0;
border:{
top: 1px solid #000;
bottom: 0;
left: 0;
}
&:last-of-type{
padding-bottom: 0;
text-align: right;
&:before{
border-width: 5px 0 5px 10px;
border-color: transparent transparent transparent #000000;
top: 0;
right: 0;
bottom: auto;
left: auto;
transform: translateX(0) translateY(-50%);
}
p{
text-align: left;
}
}
}
&-label,
&-content{
transform: translateX(-50%);
text-align: left;
display: block;
max-width: 70%;
}
&-label{
text-align: center;
position: absolute;
top: 0;
left: 0;
transform: translateX(-50%) translateY(-120%);
}
&-content{
margin-top: 10px;
}
&-item:last-of-type &-label,
&-item:last-of-type &-content{
transform: translateX(50%);
text-align: left;
display: inline-block;
max-width: 70%;
}
&-item:last-of-type &-label{
left: auto;
right: 0;
transform: translateX(50%) translateY(-120%);
}
}
/* ボーダー有り */
&.border-dashed &-item{
border-top: 1px dashed #ccc;
padding: 10px;
&:last-of-type{
border: {
top: none;
bottom: 1px dashed #ccc;
}
}
@media(min-width : 768px){
padding: 0;
border:{
top: 1px solid #000;
left: 1px dashed #ccc;
}
&:last-of-type{
border: {
top: 1px solid #000;
right: 1px dashed #ccc;
bottom: 0;
}
}
}
}
/* ストライプ背景 */
&.bg-stripe &-item{
&:nth-of-type(odd){
background-color: #e8e8e8;
}
&:nth-of-type(even){
background-color: #fff;
}
}
@media(min-width : 768px){
&.bg-stripe &-label,
&.bg-stripe &-content{
transform: translateX(0);
text-align: left;
display: block;
max-width: 70%;
}
&.bg-stripe &-label{
transform: translateX(0) translateY(-120%);
}
&.bg-stripe &-content{
display: inline-block;
}
}
/* PCの時は矢印っぽく */
&-wrapper{
padding: 3rem 5rem;
background-color: #f0f0f0;
}
&.bg-arrow{
padding: 0;
}
&.bg-arrow &-item{
position: relative;
border: {
top: none;
}
}
@media(min-width : 768px){
&.bg-arrow{
padding: 20px 0 0;
overflow: hidden;
}
&.bg-arrow &-item{
&:before{
height: 100%;
width: 100%;
top: 0;
left: 0;
right: 0;
bottom: 0;
border:{
color: transparent;
radius: 0;
}
box-shadow: 1px -1px 2px rgba(125, 125, 125, 0.8);
transform: skew(-45deg);
transform-origin:0 0;
background: -moz-linear-gradient(45deg, rgba(0,0,0,0) 0%, rgba(0,0,0,0.3) 100%); /* FF3.6-15 */
background: -webkit-linear-gradient(45deg, rgba(0,0,0,0) 0%,rgba(0,0,0,0.3) 100%); /* Chrome10-25,Safari5.1-6 */
background: linear-gradient(45deg, rgba(0,0,0,0) 0%,rgba(0,0,0,0.3) 100%); /* W3C, IE10+, FF16+, Chrome26+, Opera12+, Safari7+ */
}
}
&.bg-arrow &-label,
&.bg-arrow &-content{
transform: translateX(0);
text-align: left;
display: block;
max-width: 70%;
}
&.bg-arrow &-label{
transform: translateX(0) translateY(-120%);
}
&.bg-arrow &-content{
display: inline-block;
}
&.bg-arrow &-item:last-of-type{
padding-bottom: 0;
text-align: right;
&:before{
border: none;
top: 0;
left: 0;
right: 0;
bottom: 0;
transform: translateX(0) translateY(0) skew(-45deg);
}
p{
text-align: left;
display: block;
}
}
}
}
/* 現在地 */
.timeline-item.now:before{
background-color: #f00;
}