monoのメモ帳

HTMLとCSSを勉強しながらはてなブログをカスタマイズ中です。

グローバルナビゲーションを作る

ブログのグローバルナビゲーションを作ったのでその過程を備忘録として残しておこうと思います。

グローバルナビゲーションを作るにあたって、どんな風にしようかと考えたのですが、カテゴリをたくさんグローバルナビゲーションに置いても大丈夫なようにするのが1つの目標です。

  • スマホで見たときは、カテゴリがたくさんあっても横スクロールで閲覧できるようにする
  • パソコンで見たときは、カテゴリは2階層にして親カテゴリにカーソルを合わせると子カテゴリがでてくるようにする
  • JavaScriptは使わずにCSSのみで上記2つを実施する

この3つです。

考えただけでちょっと複雑。

とりあえず、スマホで見たときは親カテゴリだけの表示にしようと思います。

スマホ用のグローバルナビゲーションを作る

スマホ用のグローバルナビ

まずはスマホ用のグローバルナビゲーションを作ります。

先に出来上がりはこんな感じです。

/* グローバルナビここから */
#top-editarea {
    background-color: #fff;
}
ul.global-nav {
    margin: 0;
    font-family: '游明朝','Yu Mincho',YuMincho,'Hiragino Mincho Pro',serif;
}
.global-nav-content ul {
    list-style-type: none;
    padding: 0;
}
.global-nav li {
    position: relative;
    min-width: 90px;
}
.global-nav {
    display: flex;
    justify-content: flex-start;
    text-align: center;
    overflow-x: auto;
}
.global-nav a {
    display: block;
    text-decoration: none;
    background-color: #fff;
    color: #454545;
    padding: 10px;
}
.global-nav li ul li {
    display: none;
}
ul.global-nav li:first-child > a{
    border-bottom: solid 2px var(--main-link-color);
}

まず、グローバルナビゲーションを設置する場所は、はてなブログの「ヘッダ」の「ブログタイトル下」になります。

ID名がtop-editarea

その中にグローバルナビゲーションを作っていきます。

HTMLはサンプルページに記載しておりますのでそちらをご参照ください。

グローバルナビをヘッダー下に追加する方法 - Natural

まずは、フォントとかリストマークを消したりとか、横並びはflexboxを使ってつくりました。

カテゴリ数が多くて横幅に足りなくなった時にスクロールができるようにするには

overflow-x: auto;

を親要素に設定します。

このたった1行で横にスワイプするとはみ出している部分が表示されるので意外と簡単ですよね。

子カテゴリは非表示にして、スマホで横にスワイプできることを知らせるために、最初のリスト項目に下線をつけました。

タブレット端末以上のグローバルナビゲーションを作る

パソコン用のグローバルナビ

@media (min-width: 768px) {
    ul.global-nav li:first-child > a{
        border-bottom: none;
    }
    .global-nav {
        overflow: visible;
        display: flex;
        justify-content: flex-start;
        text-align: center;
        flex-wrap: wrap;
    }
    .global-nav li {
        position: relative;
        min-width: 120px;
    }
    .global-nav li:not(:last-child)::after {
        position: absolute;
        content: "";
        border-right: solid 1px #efefef;
        width: 100%;
        height: 50%;
        top: 11px;
        left: 0;
    }
    .global-nav a {
        display: block;
        text-decoration: none;
        background-color: #fff;
        color: #454545;
        padding: 10px;
    }
    .global-nav li ul li {
        display: block;
    }
    .global-nav li ul li a:hover {
        opacity: 1;
    }
    .global-nav a:hover {
        background-color: var(--main-link-color);
    }
    .global-nav li ul {
        position: absolute;
        top: 100%;
        left: 0;
        width: 100%;
    }
    .global-nav li ul li {
        visibility: hidden;
        overflow: hidden;
        height: 0;
        transition-duration: 0.2s;
        z-index: 1;
    }
    .global-nav li:hover > ul > li {
        visibility: visible;
        overflow: visible;
        height: 44px;
    }
}
/* グローバルナビここまで */

横幅が768px以上でスクロールバーを表示するのをやめて、グローバルナビの項目が多い場合は折り返しにするので、flexboxはwrapを設定します。

あと、先ほどスマホの時に設定した、最初のリスト項目のボーダーラインを無しにして、スクロールも解除しておきます。

親カテゴリにカーソルが乗るまでは小カテゴリは非表示にしたいので

visibility: hidden;
overflow: hidden;

を設定し、カーソルが乗ったら表示させるようにするのでhoverに

visibility: visible;
overflow: visible;

を設定しました。

今日はoverflowが大活躍です。

微妙に苦労したカテゴリとの間の棒線

.global-nav li:not(:last-child)::after {
        position: absolute;
        content: "";
        border-right: solid 1px #efefef;
        width: 100%;
        height: 50%;
        top: 11px;
        left: 0;
}

カテゴリの区切り線なのですが、最初border-leftで簡単に縦線を引くだけにしようとしたのですが、borderで縦線を引くと高さが高すぎて2段になった時に繋がってしまうんです。

marginを余分につけたくなかったので、私の苦手な擬似要素で縦棒を作りました。

not(:last-child)と書くと最後の縦棒は無しになります。

雑感

JavaScriptを使うとサイトが重くなってしまうのが嫌で、できるだけ使わずにCSSだけでやってみたのですが、まずまずの仕上がりになりました。

まだ他の端末で試していないのでわかりませんが、不具合などありましたら教えていただけると嬉しいです。

カテゴリをたくさんつけたサイトはデモサイトで確認いただけます。

デモサイト:Natural

今日覚えたCSS

  • overflow-x: auto;
  • visibility: hidden;
  • overflow: hidden;
  • visibility: visible;
  • overflow: visible;
  • not(:last-child)

追記 グローバルナビにカーソルを合わせたときにpaddingの部分はカーソルが指マークに代わるのに、aタグに合わせるとカーソルが矢印になってしまうことに気づきました。

どうやら原因は擬似要素のafterにあったようで、liではなくaタグにafterをつけて解決しました。

ちょっとコードが長くなってしまいましたが、after部分の手直しはこちら

    .global-nav li a::after {
        position: absolute;
        content: "";
        border-right: solid 1px #efefef;
        width: 100%;
        height: 50%;
        top: 11px;
        left: 0;
    }
    ul.global-nav li:last-child > a::after{
        border-right: none;
    }
    ul.global-nav li ul li a::after{
        border-right: none;
    }