もくじ


Picoのヘッダー内自動メニューを消した

こないだ、Picoのブログ化をいったん置いといて、とりあえずは任意のページをメニューに表示したかったので、ChatGPTに相談しました。

Picoはcontentフォルダ直下のファイルと、contentフォルダのサブディレクトリ内にあるindex.mdファイルが自動的にメニューに表示されるんです。これって便利なようで、ちょっと不自由でもある。自由にしたかった。

削除したコードは後半でまるっと載せるので、とりあえずメニューのコードです。

ヘッダー下に追加したメニューのコード

ChatGPTが示してくれたやつ。


<div id="new-nav" role="navigation">
    <ul>
        <li><a href="{{ base_url }}/page1">Page 1</a></li>
        <li><a href="{{ base_url }}/page2">Page 2</a></li>
        <li><a href="{{ base_url }}/page3">Page 3</a></li>
    </ul>
</div>

CSSはこう。


#new-nav ul {
    display: flex;
    list-style-type: none;
}

#new-nav ul li {
    margin: 0 10px;
}

実際に追加したコード。

テンプレートのほうは、コンテナの中に入れないと広い画面で端っこに行っちゃうのと、リンク部分は{{ "URL"|link }}みたいに書く必要があるのとで。

CSSのほうは、リストが冒頭のマーカー分(表示されていなくても)スペースあいてるのを消して中央寄せするように、ChatGPTさんにコードを追加してもらいました。


<div id="new-nav" role="navigation">
  <div class="container">
    <ul>
      <li><a href="{{ "page1"|link }}">ページ1</a></li>
      <li><a href="{{ "page2"|link }}">ページ2</a></li>
      <li><a href="{{ "page3"|link }}">ページ3</a></li>
    </ul>
  </div>
</div>

#new-nav ul {
    display: flex;
    list-style-type: none;
    justify-content: center;    /* 中央寄せ */
    margin: 0;    /* 余分なスペースをなくす */
    padding: 0;    /* 余分なスペースをなくす */
}

#new-nav ul li {
    margin: 0 10px;
    padding: 0;    /* 余分なスペースをなくす */
}

細かいことはいいとして(それにしてもPicoの中身までよく知ってるなぁ)、項目が3つだけだったので、pタグで ページ1 ページ2 ページ3 みたいに書いてリンク貼ればずーっと簡単だよね?と疑問がわいた。

なぜメニューをリストで作るのか

なんでリストでメニュー作らにゃいかんの?横並びにしたりするの面倒じゃん。

ChatGPT
HTMLの <ul><li> タグは、セマンティック(意味的な)マークアップの一部として使用されます。セマンティックマークアップは、コンテンツの構造を定義するもので、それは検索エンジンのロボットやスクリーンリーダー(視覚障がいのある人のため)などにとって重要です。

p タグは通常、段落のテキストに使用されます。

なので、あなたのウェブサイトのメニューが3つの項目しか持たない場合でも、それらの項目を <ul><li> タグでマークアップすることは、ウェブサイトのアクセシビリティを向上させると同時に、検索エンジンの最適化(SEO)にも役立ちます。

ただし、p タグを使用しても技術的には間違っていませんが、それはセマンティックには適していません。そして、それが将来的にSEOやアクセシビリティの問題を引き起こす可能性があります。

ふーん。そうだったんだ、、

ブロック要素とインライン要素の認識があいまいだったので色々きいてみた

justify-content:text-align:の使い分けは?

ChatGPT
justify-contenttext-align は異なる目的で使用されるプロパティです。

  1. justify-content: これは Flexbox のコンテナ(親要素)内のアイテム(子要素)の配置を制御するためのプロパティです。これは、水平方向にアイテムを配置する方法を指定するために使用されます。例えば、justify-content: center; は、アイテムをコンテナの中央に配置します。

  2. text-align: これは、テキストの配置を制御するためのプロパティです。text-align は、テキストのブロック内でテキストを左、右、中央、または両端に揃えるために使用されます。例えば、text-align: right; は、テキストを右に揃えます。

以下は、それぞれの使い方の例です:

.container {
    display: flex;
    justify-content: center; /* 子要素を中央に配置 */
}

.text {
    text-align: center; /* テキストを中央に揃える */
}

したがって、justify-content は、Flexboxのコンテナ内のアイテムの配置を制御するのに使用され、 text-align はテキストの配置を制御するのに使用されます。

text-align:はテキストだけに効くのですか?
例えば、pタグにtext-align:を設定するほかに、divタグに設定すると中身のテキストに効いたりするのでしょうか。imgタグにはtext-align:を設定しても効きませんか?

ChatGPT
text-align は主にテキストの配置を制御するために使用されますが、他のインライン要素(例えば、<img> タグ)にも影響を与えます。

例えば、以下の HTML と CSS の例を考えてみましょう。

<div class="container">
    <p>This is some text.</p>
    <img src="path/to/image.jpg" alt="Example Image">
</div>
.container {
    text-align: center;
}

この場合、div タグの中のテキストと画像の両方が中央に配置されます。

ただし、text-align プロパティは、ブロックレベル要素(例えば、div タグ)自体の配置を制御するためには使用されません。これは、その中のインライン要素(例えば、テキスト、画像)の配置を制御します。

したがって、text-align プロパティは、テキストだけでなく、他のインライン要素にも影響を与えます。

親要素のクラスにtext-align:を指定すれば、中身のインライン要素に効くということですね?

あれ、pはブロック要素では?

ChatGPT
はい、正確には p 要素はブロック要素です。私の説明が不正確でした、申し訳ありません。

HTMLの要素はデフォルトでブロック要素、インライン要素、またはインラインブロック要素のいずれかとして分類されます。

  • ブロック要素: ブロック要素は新しい「行」を作成し、その要素の前後に改行が入ります。例えば、div, p, h1, ul などがあります。

  • インライン要素: インライン要素は新しい行を作成せず、テキストの途中に挿入することができます。例えば、<span>, <a>, <strong>, <img> などがあります。

  • インラインブロック要素: インラインブロック要素はインライン要素のように新しい行を作成せず、テキストの途中に挿入することができますが、ブロック要素のように幅や高さを持つことができます。<img> はインラインブロック要素の一例です。

ただし、CSSの display プロパティを使うことで、これらの要素の表示方法を変更することが可能です。例えば、<span> 要素はデフォルトでインライン要素ですが、display: block; を指定することでブロック要素として表示することができます。

さきほど提示してくれたこのコードを試してみたら、pも中央寄せになりました。インラインではないのに不思議?です。

ChatGPT
ごめんなさい、私の説明が不十分でした。

text-align: center; は、その要素内のインラインコンテンツ(テキストやインライン要素)を中央寄せにするものですが、ブロック要素に適用した場合、そのブロック要素内のインラインコンテンツが中央寄せになります。

なので、.containertext-align: center; を指定した場合、.container 内の p タグのテキストや <img> 要素(これはインラインブロック要素)が中央寄せになります。これは p タグがブロック要素であるにも関わらず、text-align がその中のインラインコンテンツに影響を与えるためです。

また、<img> 要素はインラインブロック要素なので、text-align: center; が影響を与えます。

ごめんなさい、私の説明が混乱させるかもしれなかったです。どうぞ、何か他の質問があれば遠慮なく聞いてください。

divの中の、pの中身であるテキストが、pの中で中央寄せされているということ?

ChatGPT
はい、その通りです。div class="container" の中にある p の中身(テキスト)が、その p の中で中央寄せされます。

ブロック要素とインライン要素の見分け?は都度調べるしかなさそうですね。でも、ブロックをインラインに変更できたりするのは、たとえばメニューのリストに使ったりするためですか?

ChatGPT
はい、要素がブロック要素かインライン要素かを見分けるには、基本的にはHTMLの仕様を知っているか、都度調べるか、あるいはその要素のデフォルトの動作を観察するしかありません。

ブロック要素をインライン要素に変更することは、様々なレイアウトやデザインのニーズに対応するために行います。例えば、メニューのリストを作成する際に、デフォルトではブロック要素である <li> 要素をインライン要素に変更して、リスト項目が水平に並ぶようにすることがあります。これは、ナビゲーションバーをデザインする際に特に役立ちます。

ただし、これは一例に過ぎず、CSSの display プロパティを使ってブロック要素をインライン要素に変更することは、様々なデザインの課題に対して使われます。

display: flex;display: inline;の違いは?

ChatGPT
display: inline;display: flex; は、要素の表示方法を変更するためのCSSのプロパティですが、異なる目的と機能を持っています。

  1. display: inline; このプロパティは、要素をインライン要素として表示することを指示します。インライン要素は、他のテキストの中に埋め込まれるような要素で、例えば <span> タグがこれに該当します。インライン要素は、上下のマージンを持たず、要素の左右のマージンやパディングのみを持ちます。また、インライン要素の幅と高さは、その中に含まれるコンテンツによって自動的に決まります。

  2. display: flex; このプロパティは、要素をフレキシブルボックスとして表示することを指示します。フレキシブルボックス、またはフレックスボックスは、アイテムの間隔や配置を容易にコントロールすることができるコンテナです。このプロパティを指定することで、コンテナ内のアイテムを水平または垂直に整列させたり、アイテム間のスペースを均等に分配したりすることができます。

display: inline; は、要素の表示タイプを変更するための基本的なプロパティで、display: flex; は、より高度なレイアウトを作成するためのプロパティです。そのため、使用する際には目的に応じて選びます。

display: flex;はインラインではないけど横並びにできるということ?

ChatGPT
はい、その通りです。

display: flex; を設定すると、その要素はフレックスコンテナになり、その子要素(フレックスアイテム)はデフォルトで横並びになります。

また、フレックスコンテナには flex-direction プロパティもあり、これを使ってアイテムを横並びにするか(row)、縦並びにするか(column)を指定できます。デフォルトは row です。

例えば、以下のようにCSSを設定すると、子要素が横並びになります。

.container {
    display: flex;
    flex-direction: row;
}

これ試してみました。親要素に設定すると、中身の子要素が、たとえばdivが横並びになったり、インライン要素が縦並びになったりしました。なんか面白い。

おまけ:Picoのヘッダー内メニューとハンバーガーメニューは、どこを削除すればいいのか

言うまでもないけど^^;、ChatGPTに助けてもらいました。

Picoが自動的にメニューを作ってくれている部分

デフォルト状態のテーマのindex.twig
ヘッダーの中にある、リストでメニューを作っている部分

メニューを取っ払って自分で新しいのを設置する!っていうときはこれを削除する。


<div id="nav" role="navigation" tabindex="-1">
  <ul>
    {% for page in pages(depthOffset=-1) if page.title and not page.hidden %}
      <li{% if page.id == current_page.id %} class="active"{% endif %}>
        <a href="{{ page.url }}">{{ page.title }}</a>
      </li>
    {% endfor %}
  </ul>
</div>

スマホ時にハンバーガーメニューにしている部分

デフォルト状態のテーマのindex.twig
ヘッダーの中にある、トグルメニューとか書いてある部分

<a id="nav-toggle" title="Toggle Menu" role="button" aria-controls="nav" aria-expanded="false" tabindex="1">
    <span class="icon-menu" aria-hidden="true"></span>
    <span class="sr-only">Toggle Menu</span>
</a>

同じくテーマのjsフォルダ内にあるpico.js
全体は短いファイルだけど、その2/3くらい。


// responsive menu
var menu = document.getElementById('nav'),
    menuToggle = document.getElementById('nav-toggle');

if (menu && menuToggle) {
    function toggleMenuEvent(event) {
        if (event.type === 'keydown') {
            if ((event.keyCode !== 13) && (event.keyCode !== 32)) {
                return;
            }
        }

        event.preventDefault();

        if (menuToggle.getAttribute('aria-expanded') === 'false') {
            menuToggle.setAttribute('aria-expanded', 'true');
            utils.slideDown(menu, null, function () {
                if (event.type === 'keydown') {
                    menu.focus();
                }
            });
        } else {
            menuToggle.setAttribute('aria-expanded', 'false');
            utils.slideUp(menu);
        }
    }

    function onResizeEvent() {
        if (utils.isElementVisible(menuToggle)) {
            menu.className = 'hidden';
            menuToggle.addEventListener('click', toggleMenuEvent);
            menuToggle.addEventListener('keydown', toggleMenuEvent);
        } else {
            menu.className = '';
            menu.removeAttribute('data-slide-id');
            menuToggle.removeEventListener('click', toggleMenuEvent);
            menuToggle.removeEventListener('keydown', toggleMenuEvent);
        }
    }

    window.addEventListener('resize', onResizeEvent);
    onResizeEvent();
}

ChatGPT
具体的には、

  • menumenuToggle の要素を取得し、
  • それぞれの click または keydown イベントに toggleMenuEvent 関数を適用し、
  • メニューが表示されているか非表示にするかを切り替える

という処理が行われています。

だそうです。

で同じくテーマのcssフォルダ内style.css

/*** BASIC LAYOUT: EXTRA SMALL DEVICES ***/のあとの、
@media (max-width: 767px) { ~ }に囲まれているのの後半、.js部分。これが三本線を作っているそうです。


.js #nav-toggle {
    display: block;
    float: right;
    width: 2em;
    margin: 0.6667em 0;
    font-size: 1.5rem;
    line-height: 2em;
    text-align: center;
    cursor: pointer;
}
.js #nav-toggle > * { vertical-align: middle;  }

スマホ閲覧時、ハンバーガーメニューはなくなりましたが、ヘッダーの下に短い言葉のメニュー3項目が常に表示されているので、わかりやすいんじゃないかなと思います。(※当サイトじゃありません)