Help us understand the problem. What is going on with this article?

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

More than 1 year has passed since last update.

擬似要素(: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
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  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
ユーザーは見つかりませんでした