質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

88.05%

JSのタブ切り替えについて、切り替え時の背景を変更したいです。

解決済

回答 2

投稿 編集

  • 評価
  • クリップ 1
  • VIEW 470

score 13

前提・実現したいこと

現在、情報系のサイトを作成しております。
サイト内にjavascriptを使って2つのタブ(タブ1、タブ2)を作成しました。

ここからが本題で、以下のような動作を実現したいと考えております。
①タブ1(背景:水色)の中身が開いている状態で、タブ2の背景が白の状態。
②タブ2をクリックした時、タブ2の背景がピンクに切り替わり、タブ1の背景が水色から白に切り替わる。

※ポカリスエット公式サイトのようなタブをイメージしていただければわかりやすいかと思います。

イメージ説明
イメージ説明

コード

    <script type="text/javascript">

        // 対象の要素を得る
        var tabs = document.getElementById('tabcontrol').getElementsByTagName('a');
        var pages = document.getElementById('tabbody').getElementsByTagName('div');

        function changeTab() {
            // ▼href属性値から対象のid名を抜き出す
            var targetid = this.href.substring(this.href.indexOf('#')+1,this.href.length);

            // ▼指定のページだけを表示する
            for(var i=0; i<pages.length; i++) {
                if( pages[i].id != targetid ) {
                    pages[i].style.display = "none";
                }
                else {
                    pages[i].style.display = "block";
                }
            }

            // ▼クリックされたタブを前面に表示する
            for(var i=0; i<tabs.length; i++) {
                tabs[i].style.zIndex = "0";
            }
            this.style.zIndex = "10";

            // ▼ページ遷移しないようにfalseを返す
            return false;
        }

        // すべてのタブに対して、クリック時にchangeTab関数が実行されるよう指定する
        for(var i=0; i<tabs.length; i++) {
            tabs[i].onclick = changeTab;
        }

        // 最初は先頭のタブを選択
        tabs[0].onclick();

    </script>
    <style type="text/css">

        /* ▼タブ領域全体 */
        #tabcontrol {
            margin: 0;
        }

        /* ▼タブ */
        #tabcontrol a {
            display: inline-block;                /* インラインブロック化 */
            border-width: 1px 1px 0px 1px;        /* 下以外の枠線を引く */
            border-color: black;                  /* 枠線の色:黒色 */
            border-radius: 0.75em 0.75em 0px 0px; /* 枠線の左上角と右上角だけを丸く */
            padding: 0.75em 3.5em;                  /* 内側の余白 */
            text-decoration: none;                /* リンクの下線を消す */
            color: black;                         /* 文字色:黒色 */
            background-color: white;              /* 背景色:白色 */
            font-weight: bold;                    /* 太字 */
            position: relative;                   /* JavaScriptでz-indexを調整するために必要 */
        }

        /* ▼タブの中身 */
        #tabbody div {
            max-width: 100%; 
            margin-top: -1px;        /* 上側にあるタブと1pxだけ重ねるために「-1px」を指定 */
            padding: 1em;            /* 内側の余白 */
            background-color: white; /* 背景色:白色 */
            position: relative;      /* z-indexを調整するために必要 */
            z-index: 0;              /* 重なり順序を「最も背面」にするため */
            min-height: 5em;         /* 最低の高さが必要なら指定(不要なら省略可) */
        }

        /* ▼タブの配色 */
        #tabcontrol a:nth-child(1) { background-color: #BBFFFF; }    /* 1つ目のタブとその中身用の配色 */
        #tabcontrol a:nth-child(2) { background-color: #FFCCFF; }    /* 2つ目のタブとその中身用の配色 */

    </style>
<html lang="ja">
<head>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
    <title>タブサンプル</title>
    <meta name="viewport" content="initial-scale=1">
</head>
<body>

    <h1>タブサンプル</h1>



    <!-- ================ -->
    <!-- ▼タブを作るHTML -->
    <!-- ================ -->
    <div class="sample-area">

        <p id="tabcontrol">
            <a href="#tabpage1">タブ1</a>
            <a href="#tabpage2">タブ2</a>
        </p>
        <div id="tabbody">
            <div id="tabpage1">タブ1の中身<br><h2>■CSS3:</h2><ul><li>テスト1</li><li>テスト2</li><li>テスト3</li><li>テスト4</li><li>テスト5</li></ul></div>
            <div id="tabpage2">タブ2の中身<br><h2>■JavaScript:</h2><ul><li>テスト6</li><li>テスト7</li><li>テスト8</li><li>テスト9</li><li>テスト10</li></ul></div>
        </div>

    </div>

</body>
</html>

補足情報(FW/ツールのバージョンなど)

sublimeで、動作がするかどうか試しています。
プログラミングは初心者なので、色々なサイトを参考にコードを書いてます。

発生している問題

実現したい内容について、そもそもjsを使えばいいのか、cssを使えばいいのかがわかりません。
他社のサイトも色々調べたりしたのですが、近しい情報がございませんでした。
どのコードを使って、どのように記述すれば動作するのかご教授お願いします。

  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 過去に投稿した質問と同じ内容の質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

質問への追記・修正、ベストアンサー選択の依頼

  • kei344

    2019/04/02 16:02

    「何」が「どのように」わからないのか、コードのどの部分で詰まっているのかなどを、出ているエラーなどと併せて、具体的に記述されたほうが回答を得られやすいと思います。

    キャンセル

  • pase

    2019/04/02 16:28

    おっしゃる通りですね。
    コードのどの部分というよりかはどのコード(js?、css?)を使えばいいのかという根本的なところからになります。また利用するコードからどう記述すればいいかも教えていただけると助かります。

    キャンセル

回答 2

+2

下記のようにすれば良いかと思います
一応、コメントアウトで変更箇所を示してあります

<html lang="ja">
<head>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
    <title>タブサンプル</title>
    <meta name="viewport" content="initial-scale=1">
</head>
<body>

    <h1>タブサンプル</h1>



    <!-- ================ -->
    <!-- ▼タブを作るHTML -->
    <!-- ================ -->
    <div class="sample-area">

        <p id="tabcontrol">
            <!-- idを追加。0スタートに変更 -->
            <!-- <a href="#tabpage1">タブ1</a>
            <a href="#tabpage2">タブ2</a> -->
            <a id="tabpage0" href="#tabpage0">タブ1</a>
            <a id="tabpage1" href="#tabpage1">タブ2</a>
        </p>
        <div id="tabbody">
            <!-- <div id="tabpage1">タブ1の中身<br><h2>■CSS3:</h2><ul><li>テスト1</li><li>テスト2</li><li>テスト3</li><li>テスト4</li><li>テスト5</li></ul></div>
            <div id="tabpage2">タブ2の中身<br><h2>■JavaScript:</h2><ul><li>テスト6</li><li>テスト7</li><li>テスト8</li><li>テスト9</li><li>テスト10</li></ul></div> -->
            <!-- id削除 -->
            <div id="">タブ1の中身<br><h2>■CSS3:</h2><ul><li>テスト1</li><li>テスト2</li><li>テスト3</li><li>テスト4</li><li>テスト5</li></ul></div>
            <div id="">タブ2の中身<br><h2>■JavaScript:</h2><ul><li>テスト6</li><li>テスト7</li><li>テスト8</li><li>テスト9</li><li>テスト10</li></ul></div>
        </div>

    </div>

    <style type="text/css">

    /* ▼タブ領域全体 */
    #tabcontrol {
        margin: 0;
    }

    /* ▼タブ */
    #tabcontrol a {
        display: inline-block;                /* インラインブロック化 */
        border-width: 1px 1px 0px 1px;        /* 下以外の枠線を引く */
        border-color: black;                  /* 枠線の色:黒色 */
        border-radius: 0.75em 0.75em 0px 0px; /* 枠線の左上角と右上角だけを丸く */
        padding: 0.75em 3.5em;                  /* 内側の余白 */
        text-decoration: none;                /* リンクの下線を消す */
        color: black;                         /* 文字色:黒色 */
        background-color: white;              /* 背景色:白色 */
        font-weight: bold;                    /* 太字 */
        position: relative;                   /* JavaScriptでz-indexを調整するために必要 */
    }

    /* ▼タブの中身 */
    #tabbody div {
        display: none; /* 追加 */
        max-width: 100%;
        margin-top: -1px;        /* 上側にあるタブと1pxだけ重ねるために「-1px」を指定 */
        padding: 1em;            /* 内側の余白 */
        background-color: white; /* 背景色:白色 */
        position: relative;      /* z-indexを調整するために必要 */
        z-index: 0;              /* 重なり順序を「最も背面」にするため */
        min-height: 5em;         /* 最低の高さが必要なら指定(不要なら省略可) */
    }

    /* ▼タブの配色 */
    /* 変更 */
    /* #tabcontrol a:nth-child(1) { background-color: #BBFFFF; }
    #tabcontrol a:nth-child(2) { background-color: #FFCCFF; } */
    #tabpage0:target{ background-color: #BBFFFF;}
    #tabpage1:target{background-color: #FFCCFF;}
</style>

<script type="text/javascript">

    // 対象の要素を得る
    var tabs = document.getElementById('tabcontrol').getElementsByTagName('a');
    var pages = document.getElementById('tabbody').getElementsByTagName('div');

    function changeTab() {
        // ▼href属性値から対象のid名を抜き出す
        // 変更
        // var targetid = this.href.substring(this.href.indexOf('#')+1,this.href.length);
        let targetid = this.href.slice(-1);

        // ▼指定のページだけを表示する
        // 変更
        // for(var i=0; i<pages.length; i++) {
        //     if( pages[i].id != targetid ) {
        //         pages[i].style.display = "none";
        //     }
        //     else {
        //         pages[i].style.display = "block";
        //     }
        // }
        for(var i=0; i<pages.length; i++) {
            if( i != targetid ) {
              pages[i].style.display = "block";
            }
            else {
              pages[i].style.display = "none";
            }
        }

        // ▼クリックされたタブを前面に表示する
        for(var i=0; i<tabs.length; i++) {
            tabs[i].style.zIndex = "0";
        }
        this.style.zIndex = "10";

        // 削除
        // ▼ページ遷移しないようにfalseを返す
        // return false;
    }

    // すべてのタブに対して、クリック時にchangeTab関数が実行されるよう指定する
    for(var i=0; i<tabs.length; i++) {
        tabs[i].onclick = changeTab;
    }

    // 最初は先頭のタブを選択
    // 変更
    // tabs[0].onclick();
    window.location.href = "#tabpage0"
    pages[0].style.display = "block";

</script>

</body>
</html>

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2019/04/02 20:31

    詳しくコードの内容を記載していただき、ありがとうございます。
    実現したいと思っていた通りに、こちらでも動作が確認できました。

    改めてありがとうございます。

    キャンセル

checkベストアンサー

+1

そもそもjsを使えばいいのか、cssを使えばいいのかがわかりません。

CSSのみで作ることも出来ますが、JavaScriptと組み合わせて使うのが簡単かと思います。

組み方にもよりますが、

  1. idに頼った記述をしない(複数設置する時に記述量が増える)
  2. JavaScriptで直接スタイルを変更するよりも、「選択された時」のクラスをCSSで用意しておくほうがコードが整理しやすい

と思います。

下記は適当に作ったので雑ですが、複数設置可能なタブ切り替えの例です。

<div class="tab-wrap">
    <div class="tab-control">
        <button class="active" type="button" data-target="page1">タブ1</button>
        <button type="button" data-target="page2">タブ2</button>
    </div>
    <div class="tab-contents">
        <div class="tab active" data-id="page1">
            <div class="tab-inner">
                タブ1の中身<br><h2>■CSS3:</h2><ul><li>テスト1</li><li>テスト2</li><li>テスト3</li><li>テスト4</li><li>テスト5</li></ul>
            </div>
        </div>
        <div class="tab" data-id="page2">
            <div class="tab-inner">
                タブ2の中身<br><h2>■JavaScript:</h2><ul><li>テスト6</li><li>テスト7</li><li>テスト8</li><li>テスト9</li><li>テスト10</li></ul>
            </div>
        </div>
    </div>
</div><!-- >.tab-wrap< -->
.tab-wrap {
  margin-bottom: 2em;
}

/* ▼タブ */
.tab-control > button {
  border: 0 none;
  border-radius: 0.75em 0.75em 0 0;
  padding: 0.75em 3.5em;
  font-weight: bold;
  background-color: #FFCCFF;
}

.tab-control > button.active {
  background-color: #BBFFFF;
}

/* ▼タブ */
.tab-contents > .tab {
  height: 0;
  overflow: hidden;
}

.tab-contents > .tab.active {
  height: auto;
}

.tab-contents > .tab > .tab-inner {
  padding: 1em;
}
document.addEventListener( 'DOMContentLoaded' , function( e ) {
    document.querySelectorAll( '.tab-wrap' ).forEach( function( tabs ) {
        tabs.querySelectorAll( '.tab-control > button' ).forEach( function( bt, i ) {
            bt.addEventListener( 'click', function( e ) {
                removeTabActive( tabs );
                bt.classList.add( 'active' );
                tabs.querySelector( '.tab[data-id="' + bt.dataset.target + '"]' ).classList.add( 'active' );
            }, false );
        } );
    } );
    function removeTabActive( tabs ) {
        tabs.querySelectorAll( '.active' ).forEach( function( a ) {
            a.classList.remove( 'active' );
        } );
    }
}, false );

動くサンプル:https://jsfiddle.net/sr6uL1w4/


【Document.querySelectorAll() - Web API | MDN】
https://developer.mozilla.org/ja/docs/Web/API/Document/querySelectorAll

【NodeList.prototype.forEach() - Web API | MDN】
https://developer.mozilla.org/ja/docs/Web/API/NodeList/forEach

【Element.classList - Web API | MDN】
https://developer.mozilla.org/ja/docs/Web/API/Element/classList

【HTMLElement.dataset - Web API | MDN】
https://developer.mozilla.org/ja/docs/Web/API/HTMLElement/dataset

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2019/04/02 20:29

    なるほど、jsとcssを組み合わせた方が楽なのですね!
    ご丁寧に詳細リンクまで添付していただきありがとうございます。
    是非作成の参考にさせていただきます。

    キャンセル

15分調べてもわからないことは、teratailで質問しよう!

  • ただいまの回答率 88.05%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

関連した質問

同じタグがついた質問を見る