【WordPress ソースコード】初級編:ポートフォリオサイト

目次

ディレクトリ構成

    
~/wp-content/themes/my-work
 ├─img
 │  ├─favicon.ico
 │  ├─icon-instagram.png
 │  ├─logo.svg
 │  ├─mainvisual-pc.jpg
 │  └─mainvisual-sp.jpg
 │
 ├─css
 │  ├─category.css
 │  └─top.css
 │
 ├─category-news.php
 ├─category-works.php
 ├─footer.php
 ├─functions.php
 ├─header.php
 ├─index.php
 ├─page.php
 ├─single.php
 └─style.css
    
  

ファイル構成の解説

カテゴリー一覧
カテゴリー一覧のテンプレートファイルは通常「category.php」を使用しますが、 今回はカテゴリーが複数存在していてそれぞれレイアウトが異なるので、 「category-news.php」「category-works.php」とカテゴリーごとにテンプレートファイルを作成しました。
カテゴリーごとにテンプレートファイルを作成する場合は、今回のように category-[カテゴリースラッグ名].php という名前でファイルを作成すると、自動でそのファイルを読み込んでくれます。
各カテゴリー一覧のレイアウトが似ている場合は、「category.php」の中でif文を使用してレイアウトを切り分ける方法もあります。
CSSファイル

今回はベースとなる「style.css」の他に、トップページ用の「top.css」と「category.css」を作成しました。中身は下記の通りです。

style.css:共通、ヘッダー、フッター、固定ページ、投稿ページ
top.css:トップページ
category.css:カテゴリー一覧

CSSファイルの作成単位に特に決まりはないので、作るサイトによって管理しやすいファイル構成で作成してください。
例えば、規模が小さいサイトであれば「style.css」だけでもいいですし、規模が大きいサイトであれば投稿ページ用、固定ページ用、○○ページ用みたいな単位で作成しても問題ありません。

category-news.php

別タブで開く
category-news.php

<?php get_header(); ?>

<main id="news" class="wrapper">
  <h1 class="page-title"><?php single_cat_title(); ?></h1>

  <?php if (have_posts()): ?>
    <dl>
      <?php while(have_posts()):the_post(); ?>
        <dt><?php the_time('Y.m.d'); ?></dt>
        <dd>
          <a href="<?php the_permalink(); ?>"><?php the_title() ?></a>
        </dd>
      <?php endwhile; ?>
    </dl>
  <?php endif; ?>
</main>

<?php get_footer(); ?>

category-works.php

別タブで開く
category-works.php

<?php get_header(); ?>

<main id="works" class="wrapper">
  <h1 class="page-title"><?php single_cat_title(); ?></h1>

  <?php if (have_posts()): ?>
    <ul class="list">
      <?php while(have_posts()):the_post(); ?>
        <li>
          <img src="<?php the_post_thumbnail_url('full'); ?>" alt="">
          <p class="title"><?php the_title(); ?></p>
          <div class="content"><?php the_content(); ?></div>
        </li>
      <?php endwhile; ?>
    </ul>
  <?php endif; ?>
</main>

<?php get_footer(); ?>

別タブで開く
footer.php

  <footer id="footer">
    <p>&copy; <?php echo bloginfo('name'); ?></p>
  </footer>

  <?php wp_footer(); ?>
</body>
</html>

functions.php

別タブで開く
functions.php

<?php

/**************************************************
CSSファイルの読み込み
**************************************************/
function my_enqueue_styles() {
  wp_enqueue_style('ress', '//unpkg.com/ress/dist/ress.min.css', array(), false, 'all');
  wp_enqueue_style('style', get_stylesheet_uri(), array('ress'), false, 'all');

  if(is_home() || is_front_page()) {
    wp_enqueue_style('top', get_theme_file_uri('css/top.css'), array('ress', 'style'), false, 'all');

  } elseif(is_category()) {
    wp_enqueue_style('category', get_theme_file_uri('css/category.css'), array('ress', 'style'), false, 'all');
  }
}
add_action('wp_enqueue_scripts', 'my_enqueue_styles');

/**************************************************
アイキャッチを有効化
**************************************************/
add_theme_support('post-thumbnails');

header.php

別タブで開く
header.php

<!DOCTYPE html>
<html lang="ja">
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <title><?php echo bloginfo('name'); ?></title>
  <meta name="description" content="<?php bloginfo('description'); ?>">
  <link rel="icon" href="<?php echo esc_url(get_theme_file_uri('img/favicon.ico')); ?>">

  <?php wp_head(); ?>
</head>

<body>
  <header id="header">
    <!--
    トップページの場合は、ロゴにh1タグを設定。
    その他のページの場合は、カテゴリータイトルやページタイトルにh1タグを使用するため、
    ロゴはdivタグを設定する。
    -->
    <?php $tag = (is_home() || is_front_page()) ? 'h1' : 'div'; ?>
    <<?php echo $tag; ?> class="site-title">
      <a href="<?php echo esc_url(home_url()); ?>">
        <img src="<?php echo esc_url(get_theme_file_uri('img/logo.svg')); ?>" alt="My Work">
      </a>
    </<?php echo $tag; ?>>
    <nav>
      <ul>
        <li><a href="<?php echo esc_url(home_url('/about/')); ?>">About</a></li>
        <li><a href="<?php echo esc_url(home_url('/category/works/')); ?>">Works</a></li>
        <li><a href="<?php echo esc_url(home_url('/category/news/')); ?>">News</a></li>
        <li><a href="<?php echo esc_url(home_url('/contact/')); ?>">Contact</a></li>
        <li>
          <a href="https://www.instagram.com/" target="_blank">
            <img class="icon" src="<?php echo esc_url(get_theme_file_uri('img/icon-instagram.png')); ?>" alt="インスタグラム">
          </a>
        </li>
      </ul>
    </nav>
  </header>

index.php

別タブで開く
index.php

<?php get_header(); ?>

<main>
  <div id="mainvisual">
    <picture>
      <source media="(max-width: 600px)" srcset="<?php echo esc_url(get_theme_file_uri('img/mainvisual-sp.jpg')); ?>">
      <img src="<?php echo esc_url(get_theme_file_uri('img/mainvisual-pc.jpg')); ?>" alt="テキストテキストテキスト">
    </picture>
  </div>

  <div class="wrapper">
    <section id="works">
      <h2 class="sec-title">Works</h2>
      <ul>
        <?php
          $args = array(
            'posts_per_page' => 6,
            'category_name' => 'works'
          );
        ?>
        <?php $posts = get_posts($args); ?>
        <?php foreach ($posts as $post): ?>
          <?php setup_postdata($post); ?>
          <li><img src="<?php the_post_thumbnail_url('full'); ?>" alt=""></li>
        <?php endforeach; ?>
        <?php wp_reset_postdata(); ?>
      </ul>
      <a class="link" href="<?php echo esc_url(home_url('/category/works/')); ?>">See More</a>
    </section>

    <section id="news">
      <h2 class="sec-title">News</h2>
      <dl>
        <?php
          $args = array(
            'posts_per_page' => 3,
            'category_name' => 'news'
          );
        ?>
        <?php $posts = get_posts($args); ?>
        <?php foreach ($posts as $post): ?>
          <?php setup_postdata($post); ?>
          <dt><?php the_time('Y.m.d'); ?></dt>
          <dd><a href="<?php the_permalink(); ?>"><?php the_title() ?></a></dd>
        <?php endforeach; ?>
        <?php wp_reset_postdata(); ?>
      </dl>
      <a class="link" href="<?php echo esc_url(home_url('/category/news/')); ?>">See More</a>
    </section>
  </div>
</main>

<?php get_footer(); ?>

page.php

別タブで開く
page.php

<?php get_header(); ?>

<main id="page" class="wrapper">
  <article>
    <h1 class="page-title"><?php the_title(); ?></h1>

    <div class="content">
      <?php the_content(); ?>
    </div>
  </article>
</main>

<?php get_footer(); ?>

single.php

別タブで開く
single.php

<?php get_header(); ?>

<main id="single" class="wrapper">
  <article>
    <h1 class="article-title"><?php the_title(); ?></h1>
    <p><?php the_time('Y/n/j'); ?></p>

    <div class="content">
      <?php the_content(); ?>
    </div>
  </article>

  <a class="link" href="<?php echo esc_url(home_url('/category/news/')); ?>">一覧に戻る</a>
</main>

<?php get_footer(); ?>

style.css

別タブで開く
style.css

@charset "UTF-8";
/*
Theme Name: my-work
*/
html {
  font-size: 100%;
}
body {
  color: #24292e;
  font-size: 0.9rem;
  min-height: 100vh;
  position: relative;
}
a {
  text-decoration: none;
  color: #24292e;
}
img {
  max-width: 100%;
  vertical-align: bottom;
}
li {
  list-style: none;
}

.wrapper {
  max-width: 960px;
  margin: 0 auto;
  padding: 0 4% 240px 4%;
}
.site-title {
  line-height: 1px;
}
.site-title a {
  display: block;
}
.page-title {
  font-size: 1.5rem;
  margin-bottom: 65px;
  text-align: center;
}
.article-title {
  font-size: 1.5rem;
  margin-bottom: 30px;
}
.sec-title {
  font-size: 1.5rem;
  text-align: center;
  margin-bottom: 65px;
}
.link {
  display: block;
  text-align: center;
  text-decoration: underline;
}

/*-------------------------------------------
ヘッダー
-------------------------------------------*/
#header {
  max-width: 960px;
  display: flex;
  justify-content: space-between;
  align-items: center;
  height: 270px;
  margin: 0 auto;
  padding: 0 4%;
}
#header ul {
  display: flex;
  padding: 10px 0;
}
#header li {
  font-size: 0.9rem;
  margin-left: 30px;
}
#header li a {
  color: #24292e;
}
#header li a:hover {
  opacity: 0.7;
}
#header li img.icon {
  width: 20px;
}

/*-------------------------------------------
フッター
-------------------------------------------*/
#footer {
  background-color: #24292e;
  color: #fff;
  font-size: 0.5rem;
  padding: 10px 20px;
  position: absolute;
  bottom: 0;
  left: 0;
  right: 0;
  text-align: center;
}

/*-------------------------------------------
固定ページ
-------------------------------------------*/
#page p {
  margin-bottom: 30px;
}
#page ul {
  margin-bottom: 30px;
}
#page .form {
  display: flex;
  flex-wrap: wrap;
  margin-bottom: 20px;
}
#page .form dt {
  width: 15%;
}
#page .form dd {
  width: 85%;
  margin-bottom: 10px;
}
#page .form dd input,
#page .form dd textarea {
  width: 100%;
  border: solid 1px #c8c8c8;
  padding: 10px;
}
#page .form dd textarea {
  height: 10rem;
}
#page .button {
  text-align: center;
}
#page .button input {
  width: 200px;
  background-color: #24292e;
  color: #fff;
  display: block;
  padding: 15px 0;
  margin: 0 auto 10px auto;
  border: solid 1px #24292e;
}
#page .button input:hover {
  background: #fff;
  color: #24292e;
}

/*-------------------------------------------
投稿ページ
-------------------------------------------*/
#single .content {
  margin: 60px 0;
}
#single .content img {
  width: 100%;
  height: auto;
}
#single .content p {
  margin-bottom: 20px;
}

/*-------------------------------------------
SP
-------------------------------------------*/
@media screen and (max-width: 600px) {
  .site-title {
    margin-top: 20px;
  }
  .page-title {
    margin: 30px 0;
  }
  .article-title {
    margin: 30px 0;
  }
  .sec-title {
    margin-bottom: 40px;
  }

  /*-------------------------------------------
  ヘッダー
  -------------------------------------------*/
  #header {
    max-width: 100%;
    height: auto;
    flex-direction: column;
  }
  #header li {
    font-size: 0.8rem;
    margin-left: 20px;
  }
  #header li:first-child {
    margin-left: 0;
  }

  /*-------------------------------------------
  固定ページ
  -------------------------------------------*/
  #page .form {
    flex-direction: column;
  }
  #page .form dt {
    width: 100%;
  }
  #page .form dd {
    width: 100%;
  }

  /*-------------------------------------------
  投稿ページ
  -------------------------------------------*/
  #single .content {
    margin: 30px 0;
  }
}

category.css

別タブで開く
category.css

@charset "UTF-8";

/*-------------------------------------------
Works
-------------------------------------------*/
#works .list {
  max-width: 640px;
  margin: 0 auto;
}
#works .list .title {
  font-weight: bold;
  margin-bottom: 10px;
}
#works .list .content p {
  margin-bottom: 10px;
}
#works .list li {
  margin-bottom: 140px;
}
#works .list li:last-child {
  margin-bottom: 0;
}
#works .list li img {
  margin-bottom: 30px;
}

/*-------------------------------------------
News
-------------------------------------------*/
#news dl {
  display: flex;
  flex-wrap: wrap;
  border-top: solid 1px #c8c8c8;
  margin-bottom: 50px;
}
#news dt {
  width: 20%;
  border-bottom: solid 1px #c8c8c8;
  padding: 30px 15px;
}
#news dd {
  width: 80%;
  border-bottom: solid 1px #c8c8c8;
  padding: 30px 15px;
}

/*-------------------------------------------
SP
-------------------------------------------*/
@media screen and (max-width: 600px) {
  /*-------------------------------------------
  Works
  -------------------------------------------*/
  #works .list li {
    margin-bottom: 60px;
  }
  #works .list li img {
    margin-bottom: 20px;
  }

  /*-------------------------------------------
  News
  -------------------------------------------*/
  #news dl {
    flex-direction: column;
  }
  #news dt {
    width: 100%;
    border-bottom: none;
    padding-bottom: 0;
  }
  #news dd {
    width: 100%;
    padding-top: 0;
  }
}

top.css

別タブで開く
top.css

@charset "UTF-8";

/*-------------------------------------------
Mainvisual
-------------------------------------------*/
#mainvisual {
  margin-bottom: 80px;
}
#mainvisual img {
  width: 100%;
  max-width: 1920px;
  height: 420px;
  object-fit: cover;
}

/*-------------------------------------------
Works
-------------------------------------------*/
#works {
  margin-bottom: 130px;
}
#works ul {
  display: flex;
  justify-content: space-between;
  flex-wrap: wrap;
  margin-bottom: 30px;
}
#works li {
  width: 31%;
  margin-bottom: 23px;
}

/*-------------------------------------------
News
-------------------------------------------*/
#news dl {
  display: flex;
  flex-wrap: wrap;
  border-top: solid 1px #c8c8c8;
  margin-bottom: 50px;
}
#news dt {
  width: 20%;
  border-bottom: solid 1px #c8c8c8;
  padding: 15px;
}
#news dd {
  width: 80%;
  border-bottom: solid 1px #c8c8c8;
  padding: 15px;
}

/*-------------------------------------------
SP
-------------------------------------------*/
@media screen and (max-width: 600px) {
  /*-------------------------------------------
  Works
  -------------------------------------------*/
  #works ul {
    flex-direction: column;
  }
  #works li {
    width: 100%;
  }

  /*-------------------------------------------
  News
  -------------------------------------------*/
  #news dl {
    flex-direction: column;
  }
  #news dt {
    width: 100%;
    border-bottom: none;
    padding-bottom: 0;
  }
  #news dd {
    width: 100%;
    padding-top: 0;
  }
}