WordPressの投稿記事(Singleページ)で全文表示ではなく抜粋表示にする方法
投稿記事をNewsPickみたく常に抜粋表示にして、ボタンを押下して、初めて全文表示出来るようにする方法を模索。
はじめはMoreタグを使おうかとおもったけど、もうちょっと工夫して、Moreタグで分割しつつ、よりスムーズに全文表示に切り替わるようにした。
はじめに single.php を全文ではなく抜粋と全文が切り替わるようにしないとねということで、single.phpをカスタマイズしてあげることにする。
<?php the_content(''); ?>
コンテンツを表示する場所は、この
<?php the_content(''); ?>
が記載されている。
これをカスタマイズします。
<?php //single.phpの冒頭にこの宣言をしてあげれば、Moreタグが動かなかった時にも動かせるはずなのでおまじないとして入れよう global $more; $more = false; ?> <div class="more-content-wrap"> <?php $content = get_the_divided_content(); ?> <input id="more_trigger" class="more-trigger" type="checkbox"> <label class="more-btn" for="more_trigger">続きを読む</label> <div class="more-extended"> <?php echo $content['before']; ?> </div> <div class="more-content"> <?php echo $content['after']; ?> </div> </div>
こんな感じ。
これだけだと、コンテンツを消しているので次に function.php など (などと書いているのは管理しずらいから機能を追加したら別ディレクトリに機能をいれて呼び出すようにしている) に $content で before と after でわけて表示することにした。
function.phpの中身はこれ
function get_the_divided_content($more_link_text = null, $stripteaser = 0, $more_file = '') { $regex = '#(<span id="more-[d]+"></span>|<span id="more-[d]+"></span>)#'; $content = get_the_content( $more_link_text, $stripteaser, $more_file ); $content = apply_filters( 'the_content', $content ); $content = str_replace( ']]>', ']]>', $content ); if(preg_match($regex, $content)) { list($content_array['before'], $content_array['after']) = preg_split($regex, $content, 2); } else { $content_array['before'] = ''; $content_array['after'] = $content; } return $content_array; }
こうすることで、コンテンツをビジュアルエディタでMoreタグボタンでわけてあげることが出来るようになる。
後は一工夫です。
ここからはCSSで表示の大きさを制御してあげます。
<input id="more_trigger" class="more-trigger" type="checkbox"> <label class="more-btn" for="more_trigger">続きを読む</label>
この箇所はチェックボックスで、以下をCSSで切り替えて表示してあげる要素になるので、簡単にいえば続きを読むボタンでチェックボックスは非表示にしてあげて、ボタンを押下したらチェックされて隠しておいたafter以下のコンテンツも表示するという方法を採っています。
CSSはこちらです。
.more-btn { background: #fb4b4b; color: #fff; text-align: center; display: block; border-radius: 5px; padding: .5em 2em; position: relative; top: 0; z-index: 2; } .more-extended { position: relative; overflow: hidden; } .more-extended::before { display: block; position: absolute; bottom: 0; left: 0; width: 100%; height: 150px; /*グラデーションで隠す高さ*/ background: -webkit-linear-gradient(top,rgba(255, 255, 255, .45) 45%,rgba(255,255,255,.7) 70%,rgba(255,255,255,.8) 80%,#fff 100%); background: linear-gradient(top, rgba(255,255,255,0.45) 45%, rgba(255,255,255,0.7) 70%, rgba(255,255,255,0.9) 80%, #fff 100%); content: ""; z-index: 1; } .more-content { position: relative; overflow: hidden; height: 40px; /*隠した状態の高さ*/ } .more-content::before { display: block; position: absolute; bottom: 0; left: 0; width: 100%; height: 100px; /*グラデーションで隠す高さ*/ background: -webkit-linear-gradient(top,rgba(255, 255, 255, .5) 50%,rgba(255,255,255,.7) 70%,rgba(255,255,255,.8) 80%,#fff 100%); background: linear-gradient(top, rgba(255,255,255,0.5) 50%, rgba(255,255,255,0.9) 70%, rgba(255,255,255,0.9) 80%, #fff 100%); content: ""; } .more-trigger { display: none; /*チェックボックスは常に非表示*/ } .more-trigger:checked + .more-btn { display: none; /*チェックされていたら、more-btnを非表示にする*/ } .more-trigger:checked ~ .more-extended, .more-trigger:checked ~ .more-content { height: auto; /*チェックされていたら、高さを戻す*/ } .more-trigger:checked ~ .more-extended::before, .more-trigger:checked ~ .more-content::before { display: none; /*チェックされていたら、more-contentのbeforeを非表示にする*/ }
これで、コーディングは完了。
このコンテンツをわける方法は、わけることでそれ以下に、広告を表示するなどの制御をするという時に使われているようですが、今回はNewsPicksのように投稿のコメントをたくさんして貰いたいという機能をつけたくて、記事ページを抜粋形式で常に表示して記事コンテンツ自体は常に隠したいということで使った方法です。
これにあわせてコメント欄を快適に使えるようにAjaxを効かせたコメント欄を用意。
これは動作的に気持ちいい動きをしてくれるし、案外ライブの更新でもスムーズに投稿出来るようになっているのでコメントをする障壁は少ない。
後は、セキュアを気をつけてあげるために、AkismitだけではなreCapchaを入れてあげて承認制も回避。
ボットのスパムコメントはコレで防げる。(本来は無理な面もあるけど、ボットからの連続投稿やチェックを回避するために時間の制限もついている)。
NewsPicksなどは登録制のSNSだから、はじめからこうした心配もなしだしね。
ただ、WordPressだとそうも行かない部分もあるので、そのあたりを調整してあげる。
そんな対処となります。