LoginSignup
1
1

More than 5 years have passed since last update.

Rails Backdrop機能(サイドバーやドロップダウンメニュー有効時後ろが暗くなるやつ)

Last updated at Posted at 2018-04-16

前回から

一度実装したbackdrop機能。
サイドバーやドロップダウンメニューがそれぞれ有効時に、それぞれのすぐ下のスタックにページ全体を覆う要素(黒色、オパシティ0.8)を表示すると言うものを自作。

http://bootstrap3.cyberlab.info/javascript/modals-options-backdrop.html#
↑ bootstrap3ではオプションで設置可能。

前回の記事の時点でフッダーが触れる、裏の裏(本文container)がスクロール可能、下手したらリンクも飛べる等粗だらけだったので改良を目指した。
出来上がった結果は一番下に書くのでそれだけ知りたい人は飛ばして下さい

position: fixed;

先ず手を付けたのがcontainerのポジションを帰るもの。
「後ろの要素 動く」だったりで一番に出て来る。
実装したら本文がスクロール可能問題は解決したがまた別問題発生。そんなもん。

今回の自分の場合layoout/applicationで

1ヘッダー
2コンテナ
3フッダー
4navバー

で構成されていた。
navバーにはトップリンク、マイページリンクなど5つの重要リンクをもっていて、コンテナのスクロールと共にスマホ最下部にピタッと付いてくる仕様にしていた。

結果position:absolute , bottom:0 で配置していたフッダーが、fixedになったコンテナに呼応して画面の最下部(navバーの直ぐ上)までせり上がってきてしまう。
と、いうか、例え一番下であってもbackdrop有効になった瞬間にページが一番上まであがってきてしまうのだ。

image.png
↑参考画https://webkikaku.co.jp/blog/htmlcss/footer-bottom/ 
記事自体はあまり関係ないです
(濃いピンク→navバー、薄ピンク→フッダー、 緑点線→backdrop  あくまでもイメージ)

overflow: hidden

じゃbootstrap3のbackdropオプションはどう処理が走ってhttp://bootstrap3.cyberlab.info/javascript/modals-options-backdrop.html#
このモーダルのような挙動をしているのか、このサイトでデベロッパーツールで弄り回した所、
bodyタグにcss: overflow が働いている事を発見、似たような動きを自分のアプリに落とし込みました。
すると前の工程で発生した問題が解決するのと入れ替わりでiphoneでうしろが触れてしまった。androidでは素晴らしい挙動を示したのですが、なんでやねん。

歴戦の情報

https://qiita.com/mimoe/items/f5f668cebb697d073553
↑iphoneではoverflowが効かない問題

結果他にも2つほど処理を掛けたりしましたが完璧な物にはならず、ggってみるとこの記事を発見。
非常に読みやすく、更に全く同じことをやっては改善を繰り返しておりましたのでこちらのブログさんのソースコードから自分の欲しい処理を自分のアプリに落とし込む形をとりました。

↓参考元
https://noji.wpblog.jp/2016/11/30/%E3%80%90%E3%81%BE%E3%81%95%E3%81%AB%E5%BA%95%E3%81%AA%E3%81%97%E6%B2%BC%E3%80%91%E3%81%82%E3%81%AE%E3%80%8C%E5%B7%A6%E5%81%B4%E3%81%8B%E3%82%89%E5%87%BA%E3%81%A6%E3%81%8F%E3%82%8B%E3%83%A1%E3%83%8B/

ソースコード

appllication.js

var scrollTop = 0;
// バックドロップ有効時処理
backdropActive = function(){
    $('.backdrop').css('display' , 'block');
    $('.fixed-bottom').css('z-index',' 989');
    element = document.getElementById('footer')
    clientRect = element.getBoundingClientRect();
    fTop = clientRect.top
    $('.sidebar_toggle').css('display','none');
    $('.footer').css({
    'position':'fixed',
    'top': fTop
    });
    scrollTop = $(window).scrollTop();
    $('body').css({
    'position':'fixed',
    'top': -scrollTop
    });
}
// バックドロップ無効時
backdropNegative = function(){
    $('.backdrop').css('display' , 'none');
    $('.fixed-bottom').css('z-index',' 1030');
    $('body').removeClass('backdrop-active');
    $('body').css('position','static');
    $('.sidebar_toggle').css('display','block');
    $(window).scrollTop(scrollTop);
    $('.footer').css({
    'position':'absolute',
    'top':''
    });
}

$(document).ready(function(){

  // ドロップバーが表示された時
  $('.dropdown').on('show.bs.dropdown',function(event){
    backdropActive()
  });

  // ドロップバーが閉じた時
  $('.dropdown').on('hidden.bs.dropdown',function(event){
    backdropNegative();
  });

  //sidebarメニューが開いたらsidebar-activeクラスを付与する
  var sidebar = $("#sidebar");
  $('.sidebar_toggle').click(function(){
    sidebar.toggleClass('sidebar--active'); 
    event.stopPropagation();
  });

  // sidebarのメニューが開いた時sidebar-activeをクラスに持っていたらbackdropをディスプレイさせる
  $('.sidebar_toggle').click(function(){
    if($('.sidebar').hasClass("sidebar--active")){
      backdropActive()
      $('.fixed-top').css('z-index','989');
    }
  });

  // backdropをクリックしたらsidebar-activeを無効、同時にbackdropも無効
  $('.backdrop').click(function(e) {
    if (!sidebar.is(e.target) && sidebar.hasClass('sidebar--active')) {
      sidebar.removeClass('sidebar--active');
      event.preventDefault();
       backdropNegative();
      $('.fixed-top').css('z-index','1030');
    }
  });

application.html
# body内
    <div class="backdrop" style="display: none;"></div>

application.scss
.backdrop {
    background-color: rgba(0,0,0,0.8);
    position: fixed;
    top: 0;
    right: 0;
    bottom: 0;
    left: 0;
    z-index: 990;
  }

1030はbootsrapの元の数値です。
990は自分のなかで何となく決めた数値です。わかりづらくてすみません。

追記 5/14

iosでinput他にfocusすると、position:fixedによる弊害でいくつか問題が発見された。
修正を行った

// スクロール禁止(ios用)
no_scroll = function(){
  $(window).on('touchmove.noScroll', function(e) {
    e.preventDefault();
  });
}

// スクロール禁止 解除
on_scroll = function(){ $(window).off('.noScroll');}

var scrollTop = 0;
backdropActive = function(){
  $('.backdrop').css('display' , 'block');
  $('.fixed-bottom').css('z-index',' 989');
  element = document.getElementById('footer')
  clientRect = element.getBoundingClientRect();
  fTop = clientRect.top
  $('.footer').css({
    'position':'fixed',
    'top': fTop
  });
  $('.sidebar_toggle').css('display','none');
  scrollTop = $(window).scrollTop();
  $('body').css({
    'top': (-scrollTop-100) + 'px',
    'overflow':'hidden'
  })
  no_scroll();
}

backdropNegative = function(){
  $('.backdrop').css('display' , 'none');
  $('.fixed-bottom').css('z-index',' 1030');
  $('body').removeClass('backdrop-active');
  $('body').css('overflow','');
  $('.sidebar_toggle').css('display','block');
  $(window).scrollTop(scrollTop);
  $('.footer').css({
    'position':'absolute',
    'top':''
  });
  on_scroll();
}


 textarea {
    font-size: 16px;
    transform: scale(0.8);
  }
 <%= f.text_area :body, id:'no-pinch' , class:'frame-none text-white submit-form px-4', placeholder:"入力してください" %>

、
、
、
<script>
$(document).ready(function(){
 inputElem = document.querySelector('#no-pinch')
  inputElem.addEventListener('focus', function() {
   scrollTop = $(window).scrollTop();
   $('#bottom-nav').hide();
  });
  inputElem.addEventListener('blur', function() {
    setTimeout(function() {
     $('#bottom-nav').show(); 
    }, 200);
  });
});
  </script>

iosでは16px以下で設定しているとピンチインしてしまうのでこのCSSとjsで対応

1
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
1