Qiita Teams that are logged in
You are not logged in to any team

Log in to Qiita Team
Community
OrganizationEventAdvent CalendarQiitadon (β)
Service
Qiita JobsQiita ZineQiita Blog
4
Help us understand the problem. What are the problem?

More than 3 years have passed since last update.

【擬似要素をjsで動的に】幅100%のサブメニューを設置しホバーで吹き出しつける

擬似要素(:beforeとか:afterとか)のjsからの操作が地味に調べたのと応用できそうだったのでメモ

【ゆるゆる募】もっと簡単な方法あったのに的なつっこみ

やりたいこと

  • グローバルメニュー設置
  • サブメニューはブラウザ幅100%
  • グローバルメニュー内の項目をマウスオーバーしたら該当の項目に向けて吹き出しを出す
  • PCのみの表示だけ作ればおk

要するにこういうこと

サンプル.jpg

サンプルコード

課題

  • 擬似要素は非DOMなのでjsから操作するのにstyleを追加しないといけない。

非DOMイメージ
私の考える非DOMのイメージ

  • 動的に位置を取得しないといけないのでcssのclass追加でごまかせない
  • なるべくコードを短くしたい ← これ

実装

擬似要素の操作

下記を参考に
Change :hover CSS properties with JavaScript

マウスがグロナビ内のメニューに来たときにブラウザサイズから位置をとって、headにstyle要素をTextNodeで追加
マウスが離れた時にスタイル自体を削除

var nav, style;
nav = $('#global-nav ul li.outline a.menu');
style = document.createElement('style');

nav.on('mouseenter', function(e){// マウス乗っかった時
  var target, clientRect, leftpx, css;
  target = e.target;

  clientRect = target.getBoundingClientRect() ;

  // 座標とる。なんとなく真ん中あたりにくるように調整
  leftpx = window.pageXOffset + clientRect.left + 70;

  css = '#global-nav ul li.outline ul:after{ left: ' + leftpx +'px; }';

  style.appendChild(document.createTextNode(css));

  document.getElementsByTagName('head')[0].appendChild(style);


}).on('mouseleave', function(){// マウス離れた時

  document.getElementsByTagName('head')[0].removeChild(style);
});

あれ?マウスエンターの範囲が狭いので位置取得失敗するよ

これだと、サブメニュー内のメニューに移動する時に
サンプル2.jpg

こういう悲しいことになったので、サブメニューからマウスが離れたらstyleを削除するように変更

var submenu, nav, style;
submenu = $('#global-nav ul li.outline ul');
style = document.createElement('style');

nav.on('mouseenter', function(e){// マウス乗っかった時
  var target, clientRect, leftpx, css;
  target = e.target;

  clientRect = target.getBoundingClientRect() ;

  // 座標とる。なんとなく真ん中あたりにくるように調整
  leftpx = window.pageXOffset + clientRect.left + 70;

  css = '#global-nav ul li.outline ul:after{ left: ' + leftpx +'px; }';

  style.appendChild(document.createTextNode(css));

  document.getElementsByTagName('head')[0].appendChild(style);

});
 submenu.on('mouseleave', function(){
  document.getElementsByTagName('head')[0].removeChild(style);
});
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
4
Help us understand the problem. What are the problem?