🏗️ テーマ基盤中級
テーマレイアウト
Shopify テーマの基本レイアウトファイル。ヘッダー、サイドバーカテゴリメニュー、メインコンテンツエリア、フッターを備えた HTML 構造と CSS スタイルを定義する。
用途
すべてのページテンプレートで共通となるサイト全体のレイアウト基盤として機能。ロゴ、検索フォーム、カートリンク、カテゴリ navigation を統一的に表示する。
設置場所
layout/theme.liquid に配置。Shopify 管理画面では「テーマ > コード編集 > layout/theme.liquid」で直接編集する。すべてのテンプレートが自動的にこのレイアウトを継承する。
注意点
メタオブジェクトの `shop.metaobjects.category_metaobject.hardware.children_categories.value` が存在することが前提となるため、管理画面で該当メタオブジェクトを事前に作成・構成しておく必要がある。モバイル表示(768px以下)ではサイドバーが非表示になるため、検索と主要カテゴリリンクがヘッダーの代替として十分機能することを確認する。`#cart-item-count` 要素は JavaScript で動的に更新される想定のため、カート追加時の更新処理が別途実装されているか確認する。
コード
250 行 / liquid<!doctype html>
<html lang="en">
<head>
<meta>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>McLiquid</title>
<link rel="icon" type="image/png" href="{{ 'favicon.png' | asset_url }}">
{% comment %} layout/theme.liquid cannot have a stylesheet tag. {% endcomment %}
<style>
body,
html {
margin: 0;
padding: 0;
height: 100%;
font-family: Arial, sans-serif;
}
.header {
background-color: #f8f8f8;
padding: 0.5rem;
border-bottom: 2px solid #f0c040;
display: flex;
justify-content: space-between;
align-items: center;
gap: 2em;
}
.header .logo {
font-size: 24px;
font-weight: bold;
color: #2e7d32;
}
.header-row {
display: flex;
justify-content: space-between;
align-items: center;
gap: 2em;
flex-grow: 1;
}
.header .search {
flex-grow: 1;
}
.header .search input {
width: 100%;
padding: 5px;
font-size: 16px;
}
.header .links {
display: flex;
gap: 15px;
}
.footer a {
text-decoration: none;
color: inherit;
}
.cart-links {
display: flex;
gap: 1rem;
}
.cart-links a {
text-decoration: none;
color: #2e7d32;
text-transform: uppercase;
font-weight: bold;
}
.cart-links a:hover {
text-decoration: underline;
}
body {
height: 100vh;
display: flex;
flex-direction: column;
}
.container {
display: flex;
flex-grow: 1;
overflow-y: hidden;
}
.sidebar {
width: 250px;
background-color: #f0f0f0;
border-right: 1px solid #ddd;
height: 100%;
flex-shrink: 0;
}
@media (max-width: 768px) {
.sidebar {
display: none;
}
.header {
flex-direction: column;
align-items: flex-start;
gap: 0.5rem;
}
.header-row {
width: 100%;
}
}
.main-content {
flex-grow: 1;
height: 100%;
overflow-y: auto;
}
.main-content h2 {
margin-top: 0;
}
.main-content .items {
display: flex;
flex-wrap: wrap;
gap: 20px;
}
.main-content .item {
width: 100px;
text-align: center;
}
.main-content .item img {
width: 100%;
height: auto;
}
.footer {
background-color: #f8f8f8;
padding: 10px;
text-align: center;
border-top: 1px solid black;
}
.sidebar ul {
list-style-type: none;
padding: 0;
margin: 0;
display: flex;
flex-direction: column;
gap: 0.25rem;
}
.sidebar ul li a {
text-decoration: none;
color: #333; /* Dark gray color */
font-size: 0.8rem;
transition: color 0.3s ease;
}
.sidebar ul li a:hover {
color: #2e7d32; /* Green color on hover */
}
.sticky-header {
font-size: 1rem;
font-weight: normal;
margin: 0;
position: sticky;
top: 0;
background-color: white;
border-bottom: 1px solid black;
padding: 0.5rem;
z-index: 1;
}
.categories {
height: 100%;
overflow-y: auto;
padding: 0.5rem;
}
</style>
{{ content_for_header }}
</head>
<body data-instant-mousedown-shortcut data-instant-intensity="viewport-all">
<nav class="header">
<div class="logo"><a href="/" style="text-decoration: none; color: #2e7d32">McLiquid</a></div>
<div class="header-row">
<div class="search">
<form method="get" action="{{ routes.search_url }}">
<input
type="text"
placeholder="Search"
name="q"
value="{{ search.terms | escape }}"
>
</form>
</div>
<div class="cart-links">
<a href="/cart"
>Order (<span
{% comment %} Note: #cart-item-count is updated from single-collection.liquid when products are added to cart {% endcomment %}
id="cart-item-count"
>
{{- cart.items.size -}}</span
>)</a
>
</div>
</div>
</nav>
<div class="container">
{% if template.name != 'cart' %}
<div class="sidebar">
<h3 class="sticky-header" style="background-color: inherit">Choose a Category</h3>
<div class="categories">
<ul>
{% for child in shop.metaobjects.category_metaobject.hardware.children_categories.value %}
<li>
<a href="{{ child.system.url }}" class="prefetch">{{ child.name }}</a>
</li>
{% endfor %}
</ul>
</div>
</div>
{% endif %}
<div class="main-content">
{{ content_for_layout }}
</div>
</div>
<div class="footer">
<p>
Home | Location | Returns | <a href="https://shopify.com/careers">Careers</a> |
<a
style="display: inline-flex; align-items: center; vertical-align: middle;"
href="https://github.com/shopify/mcliquid-theme"
><img
width="16"
height="16"
src="{{'github_favicon.svg'| asset_url}}"
style="margin-right: 4px; vertical-align: middle;"
>
shopify/mcliquid-theme</a
>
</p>
</div>
<script type="speculationrules">
{
"prefetch": [
{
"source": "document",
"eagerness": "eager",
"where": { "selector_matches": ".prefetch" }
}
],
"prerender": [
{
"source": "document",
"eagerness": "moderate",
"where": { "selector_matches": ".prefetch" }
}
]
}
</script>
</body>
</html>
出典・ライセンス
- Repository:
- https://github.com/Shopify/mcliquid-theme
- License:
- MIT
このコードは Shopify 著作の MIT ライセンスソースです。 原本の著作権は Shopify が保有します。日本語訳は ALSEL によるものです。
関連項目
🏗️ テーマ基盤中級
セクションスキーマのカスタムブロック定義
セクションの schema ブロック内でカスタムブロックタイプを定義する方法を示すサンプル。@theme と _private というプレフィックスで異なるブロック種別を宣言する。
📁 theme-tools·MIT·7 行
🏗️ テーマ基盤初級
セクション呼び出しのフォーマット
Liquid の section タグを複数行に記述する際の正しいフォーマット例。タグ名を改行で分割しても正しく認識される書き方を示す。
📁 theme-tools·MIT·7 行
🏗️ テーマ基盤初級
レイアウトテンプレートの指定
Liquid の `layout` タグを使い、テーマのレイアウトファイルを指定する構文。複数のレイアウト候補と whitespace 制御(ダッシュ記号)の使い方を示す。
📁 theme-tools·MIT·8 行
🏗️ テーマ基盤上級
Liquid フォーマッター互換のセクション表記
Prettier Liquid プラグインのテストケースで、セクションタグの様々な書式を検証する。異なる間隔・改行・ホワイトスペーストリミングの組み合わせでもセクション名が崩れないことを確認する。
📁 theme-tools·MIT·9 行
🏗️ テーマ基盤初級
基本的なHTMLレイアウト
Prettier Liquid プラグインのテスト用に作られた最小限の HTML テンプレート。DOCTYPE から body タグまでの基本的なドキュメント構造を示す。
📁 theme-tools·MIT·10 行
🏗️ テーマ基盤上級
layout タグのフォーマット
Liquid の layout タグの書式をコード品質ツール(Prettier)でフォーマットするテストケース。スペースや改行位置の違いを正規化し、レイアウト名が壊れないことを検証する。
📁 theme-tools·MIT·10 行