@inorisinga

Are you sure you want to delete the question?

Leaving a resolved question undeleted may help others!

css first-of-type リストの入れ子の場合

Q&A

Closed

解決したいこと

jqueryを使って、リストの開閉(アコーディオン)をやっています。
それに合わせて、cssでその開閉部分のデザインを行おうとしております。
その際に、first-of-type、second-of-type…で一つ目の要素、二つ目の要素をそれぞれ指示しようとしているのですが、うまくいきません。
下記のように、liの中にulを入れると、first-of-typeが効かず、全部の項目を操作してしまいます。

該当するソースコード

<html>
    <head>
        <meta charset="utf-8">
        <style>
            .navSub:first-of-type {
                background: #ff0000;
            }
        </style>
    </head>
    <body>
        <nav id="nav">
            <ul>
                <li><a href="">ホーム</a></li>
                <li>
                    <a href="javascript:void(0);" class="navToggleTitle">開閉メニュー</a>
                    <ul class="navSub">
                        <li><a href="">サブメニュー1</a></li>
                        <li><a href="">サブメニュー2</a></li>
                        <li><a href="">サブメニュー3</a></li>
                    </ul>
                </li>
                <li><a href="">タイトル</a></li>
                <li>
                    <a href="javascript:void(0);" class="navToggleTitle">開閉メニュー2</a>
                    <ul class="navSub">
                        <li><a href="">2サブメニュー1</a></li>
                        <li><a href="">2サブメニュー2</a></li>
                        <li><a href="">2サブメニュー3</a></li>
                    </ul>
                </li>
            </ul>
        </nav>
    </body>
</html>

一方下記のように、liの中にulを入れなければ、first-of-typeがうまく効きます。
しかしながら、jqueryの開閉(slideToggle)を使うためには、liの中にulを入れないと
今度は開閉ができなくなってしまいます。
どちらも機能するようにするにはどのようにしたらよいかアドバイスをお願いいたします。

<html>
    <head>
        <meta charset="utf-8">
        <style>
            .navSub:first-of-type {
                background: #ff0000;
            }
        </style>
    </head>
    <body>
        <nav id="nav">
            <ul>
                <li><a href="">ホーム</a></li>
                <li>
                    <a href="javascript:void(0);" class="navToggleTitle">開閉メニュー</a>
                </li>
                    <ul class="navSub">
                        <li><a href="">サブメニュー1</a></li>
                        <li><a href="">サブメニュー2</a></li>
                        <li><a href="">サブメニュー3</a></li>
                    </ul>
                <li><a href="">タイトル</a></li>
                <li>
                    <a href="javascript:void(0);" class="navToggleTitle">開閉メニュー2</a>
                </li>
                    <ul class="navSub">
                        <li><a href="">2サブメニュー1</a></li>
                        <li><a href="">2サブメニュー2</a></li>
                        <li><a href="">2サブメニュー3</a></li>
                    </ul>
            </ul>
        </nav>
    </body>
</html>
0 likes

1Answer

:first-of-type の挙動を誤解しているようです。 first-of-type は普通 要素の種類名:first-of-type と書くもので、「兄弟要素(同じ階層にある要素)の中でその種類の最初のもの」にマッチします。 i:first-of-type を例にすると以下のようになります。

<style>
    div > i:first-of-type { background: #ff0000; }
</style>
<div>
    <i>兄弟の i 要素の中で最初なのでマッチする</i>
    <b>b 要素なのでマッチしない</b>
    <i>兄弟の i 要素の中で2番目なのでマッチしない</i>
    <div>
        <i>兄弟の i 要素の中で最初なのでマッチする</i>
        <i>兄弟の i 要素の中で2番目なのでマッチしない</i>
    </div>
</div>
<div>
    <i>兄弟の i 要素の中で最初なのでマッチする</i>
    <i>兄弟の i 要素の中で2番目なのでマッチしない</i>
</div>

すべての階層について最初の i 要素がマッチししていますね。階層が変われば「最初」のカウントがリセットされることに注意してください。

ここで :first-of-type のように要素の種類名を省略すると、すべての種類の要素について同様のマッチを行います。

<style>
    div > :first-of-type { background: #ff0000; }
</style>
<div>
    <i>兄弟の i 要素の中で最初なのでマッチする</i>
    <b>兄弟の b 要素の中で最初なのでマッチする</b>
    <i>兄弟の i 要素の中で2番目なのでマッチしない</i>
    <b>兄弟の b 要素の中で2番目なのでマッチしない</b>
</div>

さらに .navSub:first-of-type のようにクラスセレクタをつけると、まず :first-of-type のマッチを行った上で、その結果の要素が navSub クラスを持っているかをチェックして絞り込みます。

<style>
    div > .navSub:first-of-type { background: #ff0000; }
</style>
<div>
    <i class="navSub">兄弟の i 要素の中で最初で、かつ navSub クラスを持っているのでマッチする</i>
    <i>兄弟の i 要素の中で2番目なのでマッチしない</i>
</div>
<div>
    <i>兄弟の i 要素の中で最初だが、 navSub クラスを持っていないのでマッチしない</i>
    <i class="navSub">兄弟の i 要素の中で2番目なので、 navSub クラスを持っていてもマッチしない</i>
</div>

言い換えれば「兄弟の同種要素の中で最初に現れるもので、かつnavSub クラスを持っているもの」にマッチします。

質問の1つ目のコードに戻れば、複数ある <ul class="navSub"> は、どれも「兄弟の ul 要素の中で最初に現れるもので、かつ navSub クラスを持っているもの」なので、どれも .navSub:first-of-type にマッチするということです。


さて、ご質問の意図である「階層に関係なく最初に現れた .navSub にマッチする」セレクタですが、 CSS では書けないと思います。最初の ul にだけ何か別のクラスも追加しておいてそのクラスにマッチするスタイルを書くか、 jQuery の $('.navSub').get(0) で取得して動的にスタイルを当てるとよさそうです。

0Like

Comments

  1. @inorisinga

    Questioner

    ご回答ありがとうございます!
    cssでは無理とのことで、それはそれで納得いたしました。
    jQuery等模索したいと思います。
    この度は、ありがとうございました。

Your answer might help someone💌