プログラミング成果物

トップページ用ウィジェットの作成

このブログの備忘録的側面が大きすぎて、他の人に自分がどんなことしてるか見てもらうのに適していなかったので、トップページを刷新。
真面目に書いた記事には「成果物」カテゴリをつけて、そのカテゴリがついた記事だけ一覧表示させるウィジェットを作った。
なんかもっと王道なやり方がある気がするが、目的は達成できたのでよしとする。
共同作成者のChatGPTには感謝申し上げます。

↓作ったトップページ

成果物ウィジェット

「成果物」カテゴリがついた記事を、新しい順に10件表示する。
外観 > テーマファイルエディタ > functions.phpに記載

function custom_category_card_widget() {
    $args = array(
        'post_type'      => 'post',
        'posts_per_page' => 10,
        'category_name'  => 'seikabutsu',
    );
    $query = new WP_Query($args);
    // ラッパー div を追加
    $html = '<div class="custom-widget"><div class="custom-post-cards">';
    if ($query->have_posts()) {
        while ($query->have_posts()) {
            $query->the_post();
            $link    = get_permalink();
            $title   = get_the_title();
            $date    = get_the_date('Y.n.j');
            $excerpt = get_the_excerpt();
            $excerpt = str_replace('[...]', ' ...', $excerpt);
            $thumb   = has_post_thumbnail()
                ? get_the_post_thumbnail(get_the_ID(), 'medium')
                : '<img src="https://via.placeholder.com/180x180?text=No+Image" alt="No Image">';
            // カテゴリをバッジ風に出力
            $categories = get_the_category();
            $cat_labels = '';
            if (!empty($categories)) {
                foreach ($categories as $category) {
                    $cat_labels .= '<span class="card-category">' . esc_html($category->name) . '</span>';
                }
            }
            $html .= '<a class="custom-post-card" href="' . esc_url($link) . '">';
            $html .= '  <div class="card-thumb">' . $thumb . '</div>';
            $html .= '  <div class="card-meta">';
            $html .= '    <div class="card-header">';
            $html .= '      <div class="card-title">' . esc_html($title) . '</div>';
            $html .= '      <div class="card-date">';
            $html .= '        <span class="date-text">' . esc_html($date) . '</span>' . $cat_labels;
            $html .= '      </div>';
            $html .= '    </div>';
            $html .= '    <div class="card-excerpt">' . esc_html($excerpt) . '</div>';
            $html .= '  </div>';
            $html .= '</a>';
        }
    } else {
        $html .= '<p>該当する記事がありません</p>';
    }
    $html .= '</div></div>'; // custom-post-cards と custom-widget の終了タグ
    wp_reset_postdata();
    return $html;
}
add_shortcode('seikabutsu_widget', 'custom_category_card_widget');
すべての新着記事ウィジェット
function custom_category_card_widget() {
    $args = array(
        'post_type'      => 'post',
        'posts_per_page' => 10,
        'category_name'  => 'seikabutsu',
    );
    $query = new WP_Query($args);
    // ラッパー div を追加
    $html = '<div class="custom-widget"><div class="custom-post-cards">';
    if ($query->have_posts()) {
        while ($query->have_posts()) {
            $query->the_post();
            $link    = get_permalink();
            $title   = get_the_title();
            $date    = get_the_date('Y.n.j');
            $excerpt = get_the_excerpt();
            $excerpt = str_replace('[...]', ' ...', $excerpt);
            $thumb   = has_post_thumbnail()
                ? get_the_post_thumbnail(get_the_ID(), 'medium')
                : '<img src="https://via.placeholder.com/180x180?text=No+Image" alt="No Image">';
            // カテゴリをバッジ風に出力
            $categories = get_the_category();
            $cat_labels = '';
            if (!empty($categories)) {
                foreach ($categories as $category) {
                    $cat_labels .= '<span class="card-category">' . esc_html($category->name) . '</span>';
                }
            }
            $html .= '<a class="custom-post-card" href="' . esc_url($link) . '">';
            $html .= '  <div class="card-thumb">' . $thumb . '</div>';
            $html .= '  <div class="card-meta">';
            $html .= '    <div class="card-header">';
            $html .= '      <div class="card-title">' . esc_html($title) . '</div>';
            $html .= '      <div class="card-date">';
            $html .= '        <span class="date-text">' . esc_html($date) . '</span>' . $cat_labels;
            $html .= '      </div>';
            $html .= '    </div>';
            $html .= '    <div class="card-excerpt">' . esc_html($excerpt) . '</div>';
            $html .= '  </div>';
            $html .= '</a>';
        }
    } else {
        $html .= '<p>該当する記事がありません</p>';
    }
    $html .= '</div></div>'; // custom-post-cards と custom-widget の終了タグ
    wp_reset_postdata();
    return $html;
}
add_shortcode('seikabutsu_widget', 'custom_category_card_widget');
CSS
/* ■ ウィジェット全体のラッパ */
.custom-widget .custom-post-cards {
  display: flex;
  flex-direction: column;
 &nbsp;gap: 0px; /* 成果物ウィジェット:カード間のスペースを小さく */
}
/* 新着記事ウィジェット専用:カード間の余白を完全になくす */
.custom-widget .custom-post-cards.new-posts {
  gap: 0 !important;
}
/* ■ 個別カードのベース(共通) */
.custom-widget .custom-post-card {
  display: flex;
  border: 1px solid #ddd;
  border-radius: 8px;
  background-color: #fff;
  text-decoration: none;
  color: inherit;
  overflow: hidden;
  padding: 12px;
}
/* 成果物ウィジェット専用(画像あり)の場合:外枠を削除し、左側の余白をなくす */
.custom-widget .custom-post-cards:not(.new-posts) .custom-post-card {
  border: none !important;
  padding-left: 0;
}
/* 成果物ウィジェット専用:画像とテキスト情報の間に余白を追加 */
.custom-widget .custom-post-card:not(.new-posts) .card-meta {
  margin-left: 20px;
}
/* ※ スマホ版ではこの余白を少し縮める */
@media (max-width: 768px) {
  .custom-widget .custom-post-card:not(.new-posts) .card-meta {
    margin-left: 10px;
  }
}
/* ■ サムネイル領域(成果物ウィジェット用) */
.custom-widget .card-thumb {
  width: 180px;
  height: 180px;
  flex-shrink: 0;
}
.custom-widget .card-thumb img {
  width: 100%;
  height: 100%;
  object-fit: cover;
}
/* ■ テキスト情報領域 */
.custom-widget .card-meta {
  flex: 1;
  display: flex;
  flex-direction: column;
}
/* ■ ヘッダー:タイトルと日付+カテゴリを縦に配置 */
.custom-widget .card-header {
  display: flex;
  flex-direction: column;
  margin-bottom: 8px;
}
/* タイトル(1行目) */
.custom-widget .card-title {
  font-size: 18px;
  font-weight: bold;
  margin: 0;
}
/* 日付+カテゴリ(2行目)、右揃え */
.custom-widget .card-date {
  display: flex;
  justify-content: flex-end;
  align-items: center;
  margin-top: 4px;
}
.custom-widget .date-text {
  font-size: 14px;
  color: #999;
  margin-right: 12px;
}
/* ■ カテゴリバッジ */
.custom-widget .card-category {
  display: inline-block;
  font-size: 11px;
  color: #999;
  border: 1px solid #ddd;
  border-radius: 2px;
  padding: 0 10px;
  margin-left: 8px;
  background-color: transparent;
}
/* ■ 抜粋(成果物ウィジェット用):文字サイズを少し小さくし、通常配置に */
.custom-widget .card-excerpt {
  font-size: 13px;
  color: #555;
  /* margin-top: auto; を削除して、通常の流れで配置 */
}
/* ■ スマホ版 */
@media (max-width: 768px) {
  .custom-widget .card-title {
    font-size: 16px;
  }
  .custom-widget .date-text {
    font-size: 13px;
  }
  .custom-widget .card-category {
    font-size: 10px;
    padding: 0 8px;
  }
  /* スマホではサムネイル画像を小さめに */
  .custom-widget .card-thumb {
    width: 100px;
    height: 100px;
  }
  /* スマホでは抜粋部分を非表示 */
  .custom-widget .card-excerpt {
    display: none;
  }
}
/* ■ 新着記事ウィジェット専用の調整 */
/* 個別カード(新着記事)の枠を削除し、カード内の余白も小さく */
.custom-widget .custom-post-card.new-posts {
  border: none;
  padding: 0px;
}

コメント

  1. 行と行番号が一致していて見やすいです。

    • よかったね