• aboutabout
  • servicesservices
  • worksworks
  • mediamedia
  • contactcontact
  • homeサイトトップ
  • about会社概要
  • services業務内容
  • works実績紹介
  • mediaメディア
  • contactお問い合わせ
ja/

media

メディア

  1. サイトトップ
  2. メディア
  3. プログラミングの記事
  4. Vue.jsでページャー付きの全画面表示で水平スクロールのウェブページを作成する

Vue.jsでページャー付きの全画面表示で水平スクロールのウェブページを作成する

  • 2020.11.01
  • プログラミング
  • Vue.js
Updated: 2020.11.01
近年のウェブサイトは様々なデザインのものが存在しますが、その中でもコンテンツが全画面で水平スクロールになっているものをたまに見かけます。そこで今回はCSSで全画面の水平スクロールのレイアウトにしたものに、Vue.jsを使ってコンテンツ間のページャーを設置したウェブページを作成してみたいと思います。ページ全体が大きなスライドショーのようなイメージですね、アニメーションなどと組み合わせることでより目を引くサイトデザインに仕上げることができます。それでは実際にコードをみていきます。   まずはHTMLからです。今回はコンテンツが全画面ということで、ページャーは画面下部の前面へ重なるように配置させます。そのため、body直下にページ全体のコンテナ要素を作成します。その中に水平スクロールコンテンツの要素と、ページャー要素を配置します。水平スクロール要素の中には、コンテンツ群をまとめたラッパー要素を作成し、その中にコンテンツのセクション要素をコンテンツの数だけ作成します。コンテンツセクションにはアンカー先の情報となるid属性を指定しておきます。ちなみにコンテンツ群をまとめたラッパー要素を親要素で囲った理由はCSSで水平のスクロールバーの高さ分を隠すためです。 【HTML(Pug)】※一部抜粋
body
  div.container
    div(class="horizontal-scroll-content" id="app" ref="horizontal_scroll_content")
      div.wrapper
        section.inner#section_01 セクション1のコンテンツ
        section.inner#section_02 セクション2のコンテンツ 
        section.inner#section_03 セクション3のコンテンツ
        section.inner#section_04 セクション4のコンテンツ
        section.inner#section_05 セクション5のコンテンツ
        section.inner#section_06 セクション6のコンテンツ
    div.pager
      span.prev
        span(v-if="current === 2" @click="anchor(1, 'section_01')") PREV
        span(v-else-if="current === 3" @click="anchor(2, 'section_02')") PREV
        span(v-else-if="current === 4" @click="anchor(3, 'section_03')") PREV
        span(v-else-if="current === 5" @click="anchor(4, 'section_04')") PREV
        span(v-else-if="current === 6" @click="anchor(5, 'section_05')") PREV
      span.next
        span(v-if="current === 1" @click="anchor(2, 'section_02')") NEXT
        span(v-else-if="current === 2" @click="anchor(3, 'section_03')") NEXT
        span(v-else-if="current === 3" @click="anchor(4, 'section_04')") NEXT
        span(v-else-if="current === 4" @click="anchor(5, 'section_05')") NEXT
        span(v-else-if="current === 5" @click="anchor(6, 'section_06')") NEXT
  script(src="https://cdnjs.cloudflare.com/ajax/libs/smooth-scroll/16.1.3/smooth-scroll.min.js")
  続いてページャーはデザインに合わせて作成しますが、今回は前のセクションに戻る用と、次のセクションに進む用の2つのページャーを配置させる形になります。現在表示されているセクションに合わせて、アンカー先を変更する必要があるので、v-ifディレクティブで切り替えられるようにしておきます。ページャーにはv-onディレクティブで、クリックイベントによって指定したハッシュが付与されるようにして、指定したコンテンツに移動できるようにします。最後に「smooth-scroll.js」をCDNなどで読み込んでおくことで一部ブラウザでうまく動作しないスクロール時のアニメーションが同じように挙動するようになります。   そして今回重要となるCSSです。まずはhtml要素と、水平スクロールでoverflow: auto;の設定をしている要素に対して「scroll-behavior: smooth;」を指定しておきます。こうすることでアンカーで移動した時にスクロールのアニメーションが追加されます。コンテンツは全画面で表示させるので、水平スクロールコンテンツ要素は幅と高さを画面いっぱいに広がるようにします。そして水平スクロールバーを隠すためにoverflow: hidden;とします。 【CSS(SASS)】※一部抜粋
html
  scroll-behavior: smooth
  .container
    position: relative
    .horizontal-scroll-content
      width: 100%;
      height: 100vh;
      overflow: hidden;
      .wrapper
        width: 100%;
        height: calc(100vh + 16px);
        scroll-snap-type: x mandatory;
        overflow-y: hidden;
        overflow-x: auto;
        position: relative;
        scroll-behavior: smooth;
        .inner
          width: 100%;
          height: 100%;
          scroll-snap-align: start;
          position: absolute;
          top: 0;
          left: 0;
    .pager
      position: absolute
      width: 100%;
      z-index: 1;
      left: 0;
      bottom: 0;
      display: flex;
      justify-content: space-between;
      align-items: center;
      & > span
        flex-basis: 50%;
        &.next
          text-align: right;
  続いてコンテンツ群をまとめたラッパー要素ですが、水平方向にスクロールができるよう「overflow-x: auto;」の指定をします。この時に「scroll-snap-type: x mandatory;」を指定しておくとスクロールした時にコンテンツを基準にスナップ表示させることができます。また、このラッパー要素の子要素となるコンテンツセクションを水平に並べるために「position: relative;」と設定します。最後にポイントとなるのは「height: calc(100vh + 16px);」とすることで水平スクロールバーを画面外にはみ出させて隠すことができます。   コンテンツセクション要素は絶対位置指定で水平に並べるので「position: absolute;」を忘れずに指定します。親要素でスクロールスナップの指定をしている場合には「scroll-snap-align: start;」などの設定もしておきましょう。最後にページャーをページ下部の前面に固定表示されるようにCSSを設定します。これで基本的なレイアウトが完成しましたが、現時点ではコンテンツが全て同じ場所に重なって表示されるため、最後にJavaScriptを使ってコンテンツを水平の1行内に収まるよう配置させていきます。   それではJavaScriptを見ていきます。今回はVue.jsを使うため、最初にインスタンスを作成したら対象の要素をマウントさせておきます。続けて「data」オプションでは現在表示されているコンテンツの順番を示す数値を変数として持たせておきます。 【JavaScript(Vue)】
const vueModel = new Vue({
  el: '#app',
  data() {
    return {
      current: 1
    }
  },
  mounted() {
    this.init();
    this.doObserve('.inner');
  },
  methods: {
    init() {
      const targets = document.querySelectorAll('section');
      Array.from(targets).forEach((target, index) => {
        if (index[0]) {
          target.style.left = 0;
        } else {
          target.style.left = (index * 100) + '%';
        }
      });
    },
    doObserve(element) {
      const targets = document.querySelectorAll(element);
      const options = {
        root: this.$refs.horizontal_scroll_content,
        rootMargin: '0px',
        threshold: 0.25
      };
      const observer = new IntersectionObserver((items) => {
        items.forEach((item) => {
          if (item.isIntersecting) {
            item.target.classList.add('observed');
            if(item.target.id === 'section_01') {
              this.current = 1;
            } else if(item.target.id === 'section_02') {
              this.current = 2;
            } else if(item.target.id === 'section_03') {
              this.current = 3;
            } else if(item.target.id === 'section_04') {
              this.current = 4;
            } else if(item.target.id === 'section_05') {
              this.current = 5;
            } else if(item.target.id === 'section_06') {
              this.current = 6;
            }
          } else {
            item.target.classList.remove('observed');
          }
        });
      }, options);
      Array.from(targets).forEach((target) => {
        observer.observe(target);
      });
    },
    anchor(section, hash) {
      location.hash = hash;
      this.current = section;
    }
  }
});
  「methods」オプションでは今回必要となる処理を書いていきます。必要となるのは「コンテンツを水平にレイアウトする処理」と「ページャー用のアンカー先指定の処理」と「スクロール時に現在表示されているコンテンツの情報を更新する処理」の3つになります。まず、コンテンツを水平に並べる方法ですが、全てのコンテンツ要素を配列として取得し、それに対して「forEach」メソッドを使って前のコンテンツの左側に配置されるようスタイルを設定していきます。この時にインデックス番号を使うことで、全てのコンテンツを綺麗に横一列に並べることができます。この処理を最後に「mounted」で実行させるようにすると表示された時にはレイアウトが整っている状態となります。   続いて、スクロール時に現在表示されているコンテンツの情報を更新する処理ですが、その辺りについては過去記事「JavaScriptのIntersectionObserverAPIでビューポート内での表示を検知する」で紹介している方法を活用すると便利です。表示されているコンテンツがもつid属性の値を取得し、その値に合わせて現在表示されているコンテンツを示す変数を更新します。最後に、アンカー先指定ですが、引数に表示させるコンテンツ順を示す番号とアンカーとなるハッシュの値が入るようにしておき、ハッシュが示す場所に移動させたのち、現在表示されているコンテンツの情報を更新させるようにしておきます。このメソッドはHTML側でページャーのクリックイベントとして呼び出します。   このようにしてページャー付きの全画面表示の水平スクロールで動くウェブページが完成しました。実際のサンプルはこちらにアップロードしていますのでご参考ください。   ちなみにですが、下記のようにページャーを使わない場合で、aタグで直接アンカーに飛ばす場合には、a要素に対して、「scrollIntoView({ behavior: "smooth" });」というメソッドを実行させておかないと正しくスクロールのアニメーションが実行されない場合があるので注意しておきます。
// HTML
<a href="#section_01">セクション1へ移動する</a>

// JavaScript
const paginations = document.querySelectorAll('a');
paginations.forEach((pagination) => {
  pagination.addEventListener('click', e => {
    e.preventDefault();
    const targetId = e.target.hash;
    const target = document.querySelector(targetId);
    target.scrollIntoView({ behavior: "smooth" });
  });
});
 
  今回は、Vue.jsでページャー付きの全画面表示で水平スクロールのウェブページを作成してみました。今回は紹介していませんが、全コンテンツへ自由に移動できるページネーションをつけるなどの応用もできるかと思いますので、ぜひ色々と試してみてはいかがでしょうか。今回のサンプルはこちらからご確認いただけますのでご参考に。
XでシェアLINEで送るはてブに追加

この記事を書いた人オガワ シンヤ

合同会社デザインサプライ代表兼CEO / ディレクター・ウェブデザイナー・フロントエンドエンジニアをやっています。「ウェブとデザインでヒト・モノ・サービスを繋げ新しい価値を生み出す」をコンセプトに日々奮闘中!制作中はダイエットコーラとチョコレートが欠かせないアラフォーWebクリエイター。

Sponsored Link

  • Showcase
  • Startify UI
  • Functional Gradation Generator
  • Coloooors

keyword search

categories

  • WordPress(61)
  • JavaScript(49)
  • Vue.js(48)
  • CSS(46)
  • jQuery(34)
  • Nuxt.js(22)
  • Sass(21)
  • Gulp(17)
  • webpack(16)
  • PHP(14)
  • HTML(14)
  • GSAP(11)
  • React(10)
  • Vite(9)
  • Pug(9)
  • Laravel(8)
  • Cordova(8)
  • Linux(7)
  • Next.js(6)
  • Apache(5)
  • Shopify(4)
  • REST API(4)
  • Node.js(4)
  • Smarty(3)
  • Git(3)
  • JSON(3)
  • その他プログラミング(3)
  • Google Apps API(3)
  • Bootstrap(3)
  • 環境構築・システム(3)
  • TypeScript(2)
  • EJS(2)
  • RMS(2)
  • Docker(2)
  • Instagram API(2)
  • Excel VBA(2)
  • SVG(1)
  • Dart(1)
  • ECカートASP(1)
  • Markdown(1)
  • AMP(1)
  • Nginx(1)
  • XML(1)
  • shellscript(1)
  • Ruby(1)
  • MySQL(1)

recent articles

  • Next.jsとWordPressでヘッドレスCMSのサイトを作成する#6:PWA対応とビルド時のエラー
    read more

    Next.jsとWordPressでヘッドレスCMSのサイトを作成する#6:PWA対応とビルド時のエラー

    2024.12.25/Next.js
  • Next.jsとWordPressでヘッドレスCMSのサイトを作成する#5:アナリティクス・アドセンスの導入とサイトマップ作成
    read more

    Next.jsとWordPressでヘッドレスCMSのサイトを作成する#5:アナリティクス・アドセンスの導入とサイトマップ作成

    2024.08.26/Next.js
  • Next.jsとWordPressでヘッドレスCMSのサイトを作成する#4:静的・動的ルーティングとページ作成
    read more

    Next.jsとWordPressでヘッドレスCMSのサイトを作成する#4:静的・動的ルーティングとページ作成

    2024.07.31/Next.js
  • Next.jsとWordPressでヘッドレスCMSのサイトを作成する#3:メタ情報設定・ファイル最適化・ステート管理
    read more

    Next.jsとWordPressでヘッドレスCMSのサイトを作成する#3:メタ情報設定・ファイル最適化・ステート管理

    2024.06.30/Next.js
  • Next.jsとWordPressでヘッドレスCMSのサイトを作成する#2:コーディング環境の構築
    read more

    Next.jsとWordPressでヘッドレスCMSのサイトを作成する#2:コーディング環境の構築

    2024.05.29/Next.js
  • Next.jsとWordPressでヘッドレスCMSのサイトを作成する#1:インストール・導入
    read more

    Next.jsとWordPressでヘッドレスCMSのサイトを作成する#1:インストール・導入

    2024.04.30/Next.js
  • 次の記事
  • 一覧に戻る
  • 前の記事

まだ依頼内容が決まっていなくても、ご相談ください。

課題の整理や小さな検証、UI/UX・フロントエンドの部分的な支援から始められます。

お問い合わせやご相談はこちらから

Webサイト・プロダクトの企画設計/UI・UXデザイン/フロントエンド開発合同会社デザインサプライ(DesignSupply. LLC)

Office:大阪府大阪市天王寺区清水谷町3-22
Email:info@designsupply-web.com
home
  • サイトトップ
about
  • 3つのポリシー
  • 経営理念
  • 代表・クリエイター紹介
  • 会社概要
services
  • ビジネス・プロダクト支援
  • UI/UX・フロントエンド開発支援
  • プロジェクトの進め方・支援体制
  • エデュケーション事業
works
  • 開発プロジェクト支援
  • クリエイティブ制作
  • 自社プロダクト
media
  • デザイン
  • プログラミング
  • マーケティング
  • Web開発
  • 写真・動画制作
contact
  • お問い合わせ
news
  • インフォメーション
privacy
  • プライバシーポリシー

WE THINK WITH YOU, DESIGN FOR PEOPLE, AND BUILD WHAT WORKS.

WE THINK WITH YOU, DESIGN FOR PEOPLE, AND BUILD WHAT WORKS.

© 2013 - 2026 DesignSupply.LLC
サイトトップへ
contact