EDIT

【F-light】カードレイアウト化する

2023/10/285
アイキャッチ

昨日コメントで F-light をカードレイアウトにする方法が知りたいというリクエストを頂き、試しにカスタマイズしてみたところ中々いい感じに出来ました。(コメントではブロック表示と書かれてたけど、カードレイアウトで合ってるよね?)

カードレイアウトというのは、トップページの記事一覧が、例えば公式テーマの EmporioQooQ の通常版のような感じで、各記事のカードがグリッドスタイルでレイアウトされているものです。ちなみに当ブログも元々 QooQ の通常版を使っていたので、2年ほど前まではカードレイアウトでした。(→ Internet Archive)

今回 F-light では、PC やタブレットでは記事一覧は横2列で、最上部の注目の投稿がメイン幅いっぱいの大きなカードになる Emporio に近いレイアウトにしてみました。ついでに関連記事もカードレイアウトにしてあります。もちろんレスポンシブ対応済みで、どんな画面幅でもレイアウトが崩れないようになっています。尚、人気の投稿に関してはサイドバーにあるため、リストの方がしっくりいくような気がするので変更はせず現状のままです。

カードレイアウト(PC)カードレイアウト(モバイル)
カードレイアウト(関連記事)

個人的にはリストレイアウトが好みで、当初はカード化にはあまり乗り気ではなかったのですが、いざやってみたら思いの外いい感じに。うちのブログでは合わないかもしれませんが、写真画像をアピールしたいブログだとハマるかも。もうこれ別バージョンとしてリリースしちゃおうか?なんて気にもなりかけました(笑)が、とりあえず今回はユーザー側で改造する手順の紹介だけに留めておきます。

とは言え、今回のカスタマイズは変更箇所が多くて初心者にはちょっとハードルが高いかもしれません。慣れてる人でも結構骨の折れる作業かも。という訳でカスタマイズ済のテーマファイルを Google ドライブにアップしておきましたので、カスタマイズに自信がないとか面倒くさいという方はこちらからダウンロードしてお使い下さい。

カスタマイズ手順

HTMLを編集しますので必ず予めバックアップを取ってから行って下さい。もしくはテスト用の環境(別ブログ)を用意してそちらで試されることをおすすめします。

① HTML の変更

検索で以下のコードを探します。

<b:if cond='data:view.isArchive or data:i lt 10'>

この画像のように<b:loop ...のすぐ上に<div id='article-wrapper'>を、
</b:loop>の下に</div>を挿入します。

HTML 変更箇所

② CSS の変更

/*==== 注目の投稿 ====*/
/*==== 記事一覧 ====*/
/*==== 関連記事 ====*/の所の CSS を以下の コードと入れ替えます。

注目の投稿① (常時カードデザイン)

/*==== 注目の投稿 ====*/
.article {
  display: flex;
  flex-direction: column;
  position: relative;
  transition: .3s;
  border-radius: 5px;
  box-shadow: 1px 1px 2px var(--shadow);
}
.article-category {
  position: absolute;
  top: 0;
  left: 0;
  z-index: 1;
  max-width: 40%;
  max-height: 150px;
  overflow: hidden;
  opacity: 0;
  transition: .3s;
}
.article-category-label {
  line-height: 1.7;
  margin-bottom: 5px;
  display: inline-block;
  background: #22222288;
  transition: .3s;
}
.article-category-label:first-child {
  border-top-left-radius: 5px;
}
.article-category-label a {
  display: block;
  color: var(--brand-font)!important;
  font-weight: normal;
  font-size: 1.4rem;
  padding: 3px 5px 1px 4px;
}
.article-category-label:hover {
  background: var(--brand-light);
}
.article:hover .article-category {
  opacity: 1;
}
#feat-name {
  position: absolute;
  top: 0;
  left: 0;
  font-weight: bold;
  line-height: 1;
  color: #000;
  border-top-left-radius: 5px;
  background: gold;
  padding: 6px;
}
.feat-img {
  transition: .3s;
}
.feat-img img {
  display: block;
  width: 100%;
  border-radius: 5px 5px 0 0;
}
.feat-title {
  display: flex;
  font-size: 1.82rem;
  font-weight: normal;
  margin: 0 5px 5px;
  overflow: hidden;
  height: 3.45em;
  line-height: 1.4;
  padding-top: .5em;
}
.feat-title::before {
  content: "\2605";
  padding-right: 2px;
  color: var(--brand);
  transition: .3s;
}
.article:hover .feat-title::before {
  color: gold;
}
.article:hover #feat-name {
  display: none;
}
.article:hover .feat-img {
  opacity: .7;
}
.feat-snippet {
  font-size: 1.4rem;
  line-height: 1.5;
  height: 4.5em;
  margin: 0 5px 2em;
  overflow: hidden;
  word-break: break-word;
  color: var(--dark-color);
}
@media (max-width: 600px ) {
  #FeaturedPost1 .article-category  {
    display: none;
  }
  .article:hover #feat-name {
    display: initial;
  }
}

注目の投稿② (リスト → カード可変バージョン)

個人的に注目の投稿(の画像)が大きすぎると感じたもので、こういうタイプも考えてみました。本ブログで適用していますが、かなりいい感じのバランスになって満足しています。

画面幅 600px を境にリスト → カードに変化します。デフォルトのリストデザインよりも高さを大きめに取ってあるため、タイトルは3行まで、スニペットは5行(最大139文字)まで表示できます。

注目の投稿可変バージョン
/*==== 注目の投稿 ====*/
.feat-title {
  display: flex;
  font-size: 1.82rem;
  font-weight: normal;
  margin-bottom: 5px;
  overflow: hidden;
  line-height: 1.4;
  padding-top: .5em;
  position: relative;
}
.feat-title::before {
  content: "\2605";
  padding-right: 2px;
  color: var(--brand);
  transition: .3s;
}
#FeaturedPost1 .article:hover .feat-title::before {
  color: gold;
}
.feat-snippet {
  font-size: 1.4rem;
  line-height: 1.5;
  overflow: hidden;
  word-break: break-word;
  color: var(--dark-color);
  position: relative;
}
#feat-name {
  position: absolute;
  top: 0;
  left: 0;
  font-weight: bold;
  line-height: 1;
  color: #000;
  border-top-left-radius: 5px;
  background: gold;
  padding: 6px;
}
.feat-img {
  transition: .3s;
}
#FeaturedPost1 .article:hover #feat-name {
  display: none;
}
#FeaturedPost1 .article:hover .feat-img {
  opacity: .7;
}
@media (min-width: 600px ) {
  #FeaturedPost1 .article {
    height: 250px;
  }
  .feat-img img {
    position: absolute;
    object-fit: cover;
    width: 45%;
    height: 100%;
    border-radius: 5px 0 0 5px;
  }
  .feat-title {
    height: 4.5em;
    left: 46%;
    width: 53%;
  }
  .feat-snippet {
    height: 9em;
    left: 46%;
    width: 53%;
  }
  #FeaturedPost1 .article-category {
    max-width: 45%;
    max-height: 250px;
  }
}
@media (max-width: 600px ) {
  .feat-title {
    height: 3.4em;
  }
  .feat-snippet {
    height: 4.5em;
    margin: 0 5px 2em;
  }
  .feat-img img {
    border-radius: 5px 5px 0 0;
  }
  #FeaturedPost1 .article-category  {
    display: none;
  }
  #FeaturedPost1 .article:hover #feat-name {
    display: initial;
  }
}

記事一覧

/*==== 記事一覧 ====*/
#article-wrapper {
  display: flex;
  flex-wrap: wrap;
  justify-content: space-between;
  align-items: flex-start;
}
#article-wrapper::after {
  display: block;
  content: "";
  width: 48%;
}
.article {
  flex-basis: 48%;
  display: flex;
  flex-direction: column;
  position: relative;
  margin-bottom: 1.6em;
  transition: .3s;
  border-radius: 5px;
  box-shadow: 1px 1px 2px var(--shadow);
}
.article > a {
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
}
.article:hover {
  box-shadow: 8px 8px 10px var(--shadow);
}
.article-header {
  color: var(--dark-color);
  font-size: 1.4rem;
  line-height: 1.5;
  bottom: 0;
  right: 5px;
  margin-top: 5px;
}
.article-category {
  position: absolute;
  top: 0;
  left: 0;
  z-index: 1;
  overflow: hidden;
  opacity: 0;
  transition: .3s;
}
.article-category-label {
  line-height: 1.7;
  margin-bottom: 5px;
  display: inline-block;
  background: #22222288;
  transition: .3s;
}
.article-category-label:first-child {
  border-top-left-radius: 5px;
}
.article-category-label a {
  display: block;
  color: #fff!important;
  font-weight: normal;
  font-size: 1.4rem;
  padding: 3px 5px 1px 4px;
}
.article-category-label:hover {
  background: var(--brand-light);
}
.article-category-label a:hover {
  color: var(--brand-font)!important;
}
.article-img {
  transition: .3s;
}
.article-img img {
  display: block;
  width: 100%;
  border-radius: 5px 5px 0 0;
}
.article-title {
  display: flex;
  font-size: 1.82rem;
  font-weight: normal;
  margin: 0 5px 5px;
  overflow: hidden;
  height: 3.45em;
  line-height: 1.4;
  padding-top: .5em;
}
.article-title::before {
  content: "\25A0";
  padding-right: 2px;
  color: var(--brand);
  transition: .3s;
}
.article-snippet {
  font-size: 1.4rem;
  line-height: 1.5;
  height: 4.5em;
  margin: 0 5px 2em;
  overflow: hidden;
  word-break: break-word;
  color: var(--dark-color);
}
@media (max-width: 600px ) {
  .article {
    flex-basis: 100%;
  }
  .article-category {
    opacity: 1;
  }
}
.article:hover .article-title::before {
  color: var(--sub-brand);
}
.article:hover .article-img {
  opacity: .7;
}
.article:hover .article-category {
  opacity: 1;
}

関連記事

/*==== 関連記事 ====*/
.rp-container {
  margin-top: 2em;
  display: flex;
  flex-wrap: wrap;
  justify-content: space-between;
}
.rp-container::after {
  display: block;
  content: "";
  width: 32%;
}
#related-posts a {
  position: relative;
  flex-basis: 32%;
  overflow: hidden;
  margin: 10px 0;
  border-radius: 6px;
  transition: .3s;
  box-shadow: 3px 3px 5px -2px var(--shadow);
}
.related-img img {
  object-fit: cover;
  margin: 0;
  display: block;
  width: 100%;
}
.related-date {
  position: absolute;
  right: 5px;
  bottom: 0;
  font-size: 1.4rem;
  color: var(--dark-color);
}
.related-title {
  margin: 5px 3px 1.3em 0;
  font-size: 1.4rem;
  line-height: 1.3;
  height: 5.2em;
  overflow: hidden;
  display: flex;
}
.related-title::before {
  content: "\25A0";
  color: var(--brand);
  padding-right: 2px;
  transition: .3s;
}
#related-posts a:hover {
  box-shadow: 8px 8px 10px var(--shadow);
}
#related-posts a:hover .related-title::before {
  color: var(--sub-brand);
}
@media (max-width:768px) {
  #related-posts a {
    flex-basis: 49%;
  }
  .related-title {
    height: 4em;
  }
}

以上で一応カード化は完了なのですが、このままだとサムネ画像がボヤけてしまいます。大きいサイズに変更したい場合は以下の追加作業をお願いします。

③ サムネ画像のリサイズ

注目の投稿

<div class='feat-img'/>を検索で探し
その上の<b:if cond='data:post.featuredImage'> の行番号の横の ▼ をクリックして折りたたみ、以下のコードを上書きします。
※ v1.34 以降は HTML の構造が全く異なるため、この変更は適用できません。

  <b:if cond='data:post.featuredImage'>
    <div class='feat-img'/>
<script>
(function(){const idx=<data:i/>;let img=&quot;<b:eval expr='resizeImage(data:post.featuredImage,800,&quot;16:9&quot;)'/>&quot;;let webp;if(img.match(/-k-no-nu/)){webp=img.replace(&#39;-k-no-nu&#39;,&#39;-rw-e365&#39;);}if(img.match(/lh3-testonly/)){webp=img.replace(&#39;lh3-testonly&#39;,&#39;lh3&#39;).replace(&#39;-k-no-nu&#39;,&#39;-rw-e365&#39;);}let ec=document.getElementsByClassName(&#39;feat-img&#39;)[idx];let html=&#39;&#39;;html+=&#39;&lt;img alt=&quot;<data:post.title.escaped/>&quot; height=&quot;450&quot; src=&quot;&#39;+webp+&#39;&quot; width=&quot;800&quot;/&gt;&#39;;ec.innerHTML=html;}());
</script>
      <b:else/>
      <div class='feat-img'>
        <img expr:alt='data:post.title.escaped' height='450' src='https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgPxIVQEq6xXVGIx0xpJAEYXU2Y94Et6azwn2qk6GG2428pKu5zyJL1z7fW_Axl_yVGGXvOmjJjPRSKVChPVXkIQ5gyFZwsufKkWZzShRffUWJr-rcGNioCa33gq2LGokmCWihp2gNNzATk/s800-e365-rw/noimage.png' width='800'/>
      </div>
    </b:if>

記事一覧

手順は注目の投稿と同じです。

<div class='article-img'/>を検索で探し
その上の<b:if cond='data:post.featuredImage'> の行番号の横の ▼ をクリックして折りたたみ、以下のコードを上書きします。
※ v1.34 以降は HTML の構造が全く異なるため、この変更は適用できません。

    <b:if cond='data:post.featuredImage'>
      <div class='article-img'/>
<script>
(function(){const idx=<data:i/>;let img=&quot;<b:eval expr='resizeImage(data:post.featuredImage,640,&quot;16:9&quot;)'/>&quot;;let webp;if(img.match(/-k-no-nu/)){webp=img.replace(&#39;-k-no-nu&#39;,&#39;-rw-e365&#39;);}if(img.match(/lh3-testonly/)){webp=img.replace(&#39;lh3-testonly&#39;,&#39;lh3&#39;).replace(&#39;-k-no-nu&#39;,&#39;-rw-e365&#39;);}let ec=document.getElementsByClassName(&#39;article-img&#39;)[idx];let html=&#39;&#39;;html+=&#39;&lt;img alt=&quot;<data:post.title.escaped/>&quot; height=&quot;360&quot; data-src=&quot;&#39;+webp+&#39;&quot; width=&quot;640&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjZJl0lD6fAzWtKis0dtNx5u2dCpGeRe-geIuBXUsdSZOUlrcdjPt0rlzM3ZD7oW-oeMeY8REjMGUpu__hAQV3cEgIIN9Ng0AhyKrrRxtIKWZKdDw0gaRMH_Ue31u25pV-HkiGLoR6lQ3DH/w640-c-h360-rw/blank.png&quot;/&gt;&#39;;ec.innerHTML=html;}());
</script>
      <b:else/>
      <div class='article-img'>
        <img data-src='https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgPxIVQEq6xXVGIx0xpJAEYXU2Y94Et6azwn2qk6GG2428pKu5zyJL1z7fW_Axl_yVGGXvOmjJjPRSKVChPVXkIQ5gyFZwsufKkWZzShRffUWJr-rcGNioCa33gq2LGokmCWihp2gNNzATk/s320-e365-rw/noimage.png' expr:alt='data:post.title.escaped' height='360' src='https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjZJl0lD6fAzWtKis0dtNx5u2dCpGeRe-geIuBXUsdSZOUlrcdjPt0rlzM3ZD7oW-oeMeY8REjMGUpu__hAQV3cEgIIN9Ng0AhyKrrRxtIKWZKdDw0gaRMH_Ue31u25pV-HkiGLoR6lQ3DH/w640-c-h360-rw/blank.png' width='640'/>
      </div>
    </b:if>

関連記事

<div id='related-posts'/>を検索で探し、その下の <script> 内の /*<![CDATA[*/から/*]]>*/までを以下のコードと入れ替えます。

  /*<![CDATA[*/
  !function(a,b){a.RelatedPosts||(a.RelatedPosts=b())}(this,function(){let a=function(){},b=0,c=0,d=[],e=[],f=[],g=[];return a.counter=function(){c++},a.add=function(l){let j=rp_current.match(/^https?:\/\/(.+$)/),m="",n="";null!=j&&(m="http://"+j[1],n="https://"+j[1]);for(let k=0;k<l.feed.entry.length;k++){let h=l.feed.entry[k];for(let i=0;i<h.link.length;i++)if("alternate"==h.link[i].rel){if(!(m==h.link[i].href||n==h.link[i].href)){d.push(h.link[i].href),e.push(h.title.$t);let q=h.published.$t.substr(0,10).replace(/-/g,"/");f.push(q);let a;if("media$thumbnail"in h){a=h.media$thumbnail.url;let o=/\/s72-.*\//,p=/=s72-.*$/;a.match(o)?a=a.replace(o,"/w480-h270-rw-p-e365/"):a.match(p)?a=a.replace(p,"=w480-h270-rw-p-e365"):a.match(/default.jpg/)&&(a=a.replace("default.jpg","mqdefault.webp").replace("/vi/","/vi_webp/"))}else a="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgPxIVQEq6xXVGIx0xpJAEYXU2Y94Et6azwn2qk6GG2428pKu5zyJL1z7fW_Axl_yVGGXvOmjJjPRSKVChPVXkIQ5gyFZwsufKkWZzShRffUWJr-rcGNioCa33gq2LGokmCWihp2gNNzATk/s480-e365-rw/noimage.png";g.push(a)}break}}++b==c&&function(){let l=[],a=[];for(let c=0;c<d.length;c++)-1==l.indexOf(d[c])&&(l.push(d[c]),a.push(c));let k,h=[],i=[...Array(a.length).keys()];for(;i.length>0;)k=Math.floor(Math.random()*i.length),h.push(i[k]),i.splice(k,1);let j,b=0;if(a.length>0){for(j='<div class="title">'+rp_head+'</div><div class="rp-container">';b<a.length&&b<rp_max;)j+='<a href="'+d[a[h[b]]]+'"><figure class="related-img"><img alt="関連記事サムネイル" height="270" data-src="'+g[a[h[b]]]+'" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjZJl0lD6fAzWtKis0dtNx5u2dCpGeRe-geIuBXUsdSZOUlrcdjPt0rlzM3ZD7oW-oeMeY8REjMGUpu__hAQV3cEgIIN9Ng0AhyKrrRxtIKWZKdDw0gaRMH_Ue31u25pV-HkiGLoR6lQ3DH/w480-c-h270-rw/blank.png" width="480"/></figure><div class="related-title">'+e[a[h[b]]]+'</div><div class="related-date"><svg aria-label="投稿日" class="svg svg-clock" style="vertical-align:-10%;margin-right:3px"><use href="#svg-clock"/></svg>'+f[a[h[b]]]+"</div></a>",b++;j+="</div>",document.getElementById("related-posts").innerHTML=j}}()},a})
  /*]]>*/

最後に

もし好評なようであれば、別バージョンとして正式リリースすることも検討したいと思います。