ブロックエディタ用のCSSを参考にした、よりよいコンテナの実装

以前、「本文エリア内の要素をpaddingのないコンテナとして実装する」という記事を書いた。本文エリア内の要素をすべて同じ幅でレイアウトするのではなく、ものによっては少し広めにしたりページの最大幅まで広げたりしたいという場合に、どのように実装すべきかという話。

その後、「【WordPress】 受託開発におけるハイブリッドテーマ開発」という記事を読んで、ここで紹介されているやり方の方がシンプルでよさげに見えたのでメモしておく。

具体的には、次のような実装になる。前述の記事からの抜粋。

/* 幅広・全幅ブロック以外にデフォルトコンテンツ幅を指定 */
.entry-content > *:not(.alignwide):not(.alignfull) {
  max-width: var(--wp--style--global--content-size);
}

/* 幅広ブロックに幅広コンテンツ幅を指定 */
.entry-content > *.alignwide {
  max-width: var(--wp--style--global--wide-size);
}

/* 全幅ブロックを除いて左右にオートマージンを付与する */
.entry-content > *:not(.alignfull) {
  margin-right: auto;
  margin-left: auto;
}

ここまでは以前の記事で紹介したやり方とあまり変わらない。しかし、コンテナの外側にできる余白の実装が少し違う。

.entry-content {
  padding-right: var(--wp--custom--gutter);
  padding-left: var(--wp--custom--gutter);
}

.entry-content > *.alignfull {
  margin-right: calc(var(--wp--custom--gutter) * -1);
  margin-left: calc(var(--wp--custom--gutter) * -1);
}

最大幅の実装は個々の要素が担いつつ、外側の余白は親要素に持たせておくようになっている。そして、ページいっぱいまでに広がる要素(alignfull)は例外として、ネガティブマージンで処理されている。

参考としてTwenty Twenty-Twoの実装を調べてみると、style.cssに同様の記述があった。

.wp-site-blocks,
body > .is-root-container,
.edit-post-visual-editor__post-title-wrapper,
.wp-block-group.alignfull,
.wp-block-group.has-background,
.wp-block-cover.alignfull,
.is-root-container .wp-block[data-align='full'] > .wp-block-group,
.is-root-container .wp-block[data-align='full'] > .wp-block-cover {
  padding-right: var(--wp--custom--spacing--outer);
  padding-left: var(--wp--custom--spacing--outer);
}

.wp-site-blocks .alignfull,
.wp-site-blocks > .wp-block-group.has-background,
.wp-site-blocks > .wp-block-cover,
.wp-site-blocks > .wp-block-template-part > .wp-block-group.has-background,
.wp-site-blocks > .wp-block-template-part > .wp-block-cover,
body > .is-root-container > .wp-block-cover,
body > .is-root-container > .wp-block-template-part > .wp-block-group.has-background,
body > .is-root-container > .wp-block-template-part > .wp-block-cover,
.is-root-container .wp-block[data-align='full'] {
  margin-right: calc(-1 * var(--wp--custom--spacing--outer)) !important;
  margin-left: calc(-1 * var(--wp--custom--spacing--outer)) !important;
  width: unset;
}

settings.useRootPaddingAwareAlignmentsについての解説も参考になった。

これらの例はWordPress向けの実装になっているので、少し手を加えて、単独で実装パターンとして成立するように整理した。

<div class="entry-content">
  <!-- コンテンツ幅 -->
  <h2>Hello</h2>

  <!-- コンテンツ幅 -->
  <p>Lorem ipsum dolor sit amet.</p>

  <!-- ワイド幅 -->
  <figure class="alignwide">...</figure>

  <!-- フル幅 -->
  <figure class="alignfull">...</figure>
</div>
:root {
  --spacing-outer: max(1.25rem, 5vw);
  --content-size: 40rem;
  --wide-size: 60rem;
}

.entry-content {
  padding-right: var(--spacing-outer);
  padding-left: var(--spacing-outer);
}

.entry-content > :not(.alignwide, .alignfull) {
  margin-right: auto;
  margin-left: auto;
  max-width: var(--content-size);
}

.entry-content > .alignwide {
  margin-right: auto;
  margin-left: auto;
  max-width: var(--wide-size);
}

.entry-content > .alignfull {
  margin-right: calc(var(--spacing-outer) * -1);
  margin-left: calc(var(--spacing-outer) * -1);
}

参考までに、Tailwind CSSっぽい疑似コードも示しておく。

<div class="px-outer">
  <!-- コンテンツ幅 -->
  <h2 class="max-w-content mx-auto">Hello</h2>

  <!-- コンテンツ幅 -->
  <p class="max-w-content mx-auto">Lorem ipsum dolor sit amet.</p>

  <!-- ワイド幅 -->
  <figure class="max-w-wide mx-auto">...</figure>

  <!-- フル幅 -->
  <figure class="-mx-outer">...</figure>
</div>