CSSとJavascriptでカードスタイルのリストをつくる【javascript/CSS】

css

ブログの記事一覧でよくみかけるカードスタイルのリストを作成したく、今更ながらFlexboxでレイアウトを組んだのでメモ。
子要素の高さは揃うんですが、子要素の中にある孫要素?の揃え方が分からなかったので、Javascriptでなんとかしました。

親要素とその中身をこんな風に揃えてカードっぽくしたいのだが、、、。

こんな風に孫要素の縦が揃うようにしたい

要素のテキスト量が異なると、こんな風に高さがまちまちになってしまう。。

要素が可変だと、縦が揃わなくなる

サンプルは以下ページから確認できます。
動作の確認をしてみてください!

サンプルはこちら

HTMLで構造を決める

カードの内容は上から画像⇒タイトル⇒テキスト⇒日付とします。
無難に<li>タグで書いていきます。

<ul>
    <li class="list">
        <div class="img"><img src="./images/img01.jpg"></div>
        <p class="tit">タイトルタイトルタイトルタイトルタイトル</p>
        <div class="content">
            <p class="txt">テキストテキストテキストテキストテキストテキストテキストテキストテキストテキストテキスト</p>
            <p class="info">2019年10月1日</p>
        </div>
    </li>
    <li>
        <div class="img"><img src="./images/img02.jpg"></div>
        <p class="tit">タイトルタイトルタイトルタイトル</p>
        <div class="content">
            <p class="txt">テキストテキストテキストテキストテキストテキストテキストテキスト</p>
            <p class="info">2019年3月10日</p>
        </div>
    </li>
    <li>
        <div class="img"><img src="./images/img03.jpg"></div>
        <p class="tit">タイトルタイトルタイトルタイトルタイトルタイトルタイトルタイトル</p>
        <div class="content">
            <p class="txt">テキストテキストテキストテキスト</p>
            <p class="info">2019年3月1日</p>
        </div>
    </li>
    <li>
        <div class="img"><img src="./images/img01.jpg"></div>
        <p class="tit">タイトルタイトルタイトルタイトルタイトル</p>
        <div class="content">
            <p class="txt">テキストテキストテキストテキストテキストテキストテキストテキストテキスト</p>
            <p class="info">2019年10月1日</p>
        </div>
    </li>
    <li>
        <div class="img"><img src="./images/img02.jpg"></div>
        <p class="tit">タイトルタイトルタイトルタイトル</p>
        <div class="content">
            <p class="txt">テキストテキストテキストテキストテキストテキストテキストテキストテキストテキストテキストテキストテキスト</p>
            <p class="info">2019年10月1日</p>
        </div>
    </li>
</ul>

CSSで横並びにする

flexboxで<li>要素を横並びにします。
スマホ版では縦に並ぶようにします。

ul.list {
    overflow: hidden;
}
ul.list li {
    padding: 10px;
    background: #ececec;
    list-style-type: none;
    box-sizing: border-box;
    border:3px solid #828282;
}
ul.list li:nth-child(n + 2) {
    margin-top: 10px;
}
ul.list li .img_wrap {
    overflow: hidden;
    position: relative;
}
ul.list li .img_wrap img {
    width:100%;
    vertical-align: bottom;
}
ul.list li .tit {
    font-size: 1.2em;
    color:#5a441a;
    line-height: 1.35;
    font-weight: 700;
    padding-top: 10px;
    padding-left: 1.5em;
    position: relative;
    background: #F9DFD5;
}

ul.list li .tit:before {
    content: '●';
    position: absolute;
    left: 0;
    top: 0.3em;
    font-size: 1.2em;
    color: #EDA184;
}
ul.list li .content {
    background:#F0D0E4;
    width: 100%;
    padding-top: 10px;
    margin-top: auto;
}
ul.list li .content .txt {
    margin-bottom:10px;
}
ul.list li .content .info {
    margin-top: auto;
    margin-bottom: 0;
    background:#d882cd;
    text-align:right;
}
@media screen and (min-width: 768px) {
    ul.list {
        display: -webkit-box;
        display: -ms-flexbox;
        display: flex;
        -ms-flex-wrap: wrap;
        flex-wrap: wrap;
        margin-left: -10px;
        margin-right: -10px;
    }
    ul.list li {
        display: -webkit-box;
        display: -ms-flexbox;
        display: flex;
        -webkit-box-orient: vertical;
        -webkit-box-direction: normal;
        -ms-flex-direction: column;
        flex-direction: column;
        width: calc(33.33333% - 20px);
        margin-left: 10px;
        margin-right: 10px;
    }
    ul.list li .img_wrap {
        height: 190px;
        width: 100%;
        position: relative;
    }
    ul.list li .img_wrap img {
        width:320px;
        position: absolute;
        top:50%;
        left:50%;
        transform: translate(-50%,-50%);
    }
    ul.list li:nth-child(n + 2) {
        margin-top: 0;
    }
    ul.list li:nth-child(n + 4) {
        margin-top: 20px;
    }
    ul.list li .content {
        display: -webkit-box;
        display: -ms-flexbox;
        display: flex;
        -webkit-box-orient: vertical;
        -webkit-box-direction: normal;
        -ms-flex-direction: column;
        flex-direction: column;
    }
}

Javascriptで孫要素の高さを合わせる

これだけだと子要素の高さはそろっても、その中にある孫要素の高さが合わないのでjavascripotで調整します 。

"use strict";

let resizeTime; //タイマーセット用の変数
const breakpoint = 768; //ブレイクポイント

//イベント登録
window.addEventListener('DOMContentLoaded', eventAdd);

window.addEventListener('resize', function() {
    if(resizeTime != null) {
        clearTimeout(resizeTime);
    }
    resizeTime = setTimeout(function() {
        eventAdd();
    },1000);

});

//高さを合わせる要素を指定
function eventAdd() {
    heightElm('.list li .content');
    heightElm('.list li .tit');
}
function heightElm(className) {
    const itemlist = document.querySelectorAll(className);
    console.log(itemlist);
    const items = Array.prototype.slice.call(itemlist,0);//配列に変換
    console.log(items);
    const hary = []; //要素の高さを配列で格納
    let w = 0; //windowの幅を格納

    w = window.innerWidth; //windowの幅を取得

    items.forEach(function(item,i) {
        const elmStyle = window.getComputedStyle(item);
        item.style.height = ''; //高さの初期化
        hary[i] = parseInt(elmStyle.height);
    });
    //一番高い値を取得
    const hMax = Math.max.apply(null, hary);
    //要素の高さを設定
    items.forEach(function(item,i) {
        item.style.height = w > breakpoint ? hMax + 'px': item.style.height = '';
    });
}

一通り作った後気づいたのですが、スマホ版は孫要素の高さをそろえなくて良いかも知れない、、。

コメント