多くの場合、これは非常に単純に見える問題ですが、実際に取り組み始めてみると、実際にそうなることが判明します。試してみましたが、まだ 100% 気に入ったわけではありませんが、結果を共有します。
まず、jQuery はクロス ブラウザー JavaScript として完全に有効であるため、jQuery を使用しない正当な理由は思いつきません。間違いなく、Google CDN などからロードする場合は、おそらく既にユーザー キャッシュにあるでしょう。そこで私は先に進み、小さな jQuery プラグインを作成しました (私の昔ながらの JavaScript は、正直に言うと錆びすぎです)。
最初のコード:
// jQuery plugin to create overlays
// apply to any container that contains DOM elements to be overlayed
$.fn.overlayDiv = function() {
// remove any old overlays (could be there on resize)
$(this).find('.overlay').remove();
// loop trough the remaining children
$(this).find('*').each(function() {
// cache some variables
var $el = $(this);
var $parent = $el.parent();
// make the parent relative, if not yet absolute or fixed, for easy positioning
if ($parent.css('position') !== 'fixed' && $parent.css('position') !== 'absolute') {
$parent.css('position', 'relative');
}
// prepare the css
var css = {};
css.zIndex = $el.css('z-index');
css.position = $el.css('position') == 'fixed' ? 'fixed' : 'absolute';
css.display = 'block';
// check if inline or block, and calculate settings appropriately
if ($el.css('display') == 'inline') {
// -- inline
// clone the element and render it on one line
var $clone = $el.clone();
$clone.css({
width: 'auto',
display: 'block',
whiteSpace: 'nowrap'
});
$clone.insertAfter($el);
// compare height of element and clone
if ($el.outerHeight(true) == $clone.outerHeight(true)) {
// if the $el is on a single line
css.width = $el.outerWidth(true);
css.height = $el.outerHeight(true);
css.top = $el.position().top;
css.left = $el.position().left;
// apply the styling to an overlay div and include it in the DOM
$('<div class="overlay"></div>').css(css).insertAfter($el);
} else {
// if the $el is on multiple lines (we need up to 3 divs to overlay)
// -- this part of the code needs improving --
var lineHeight = $clone.outerHeight();
var totalWidth = $clone.outerWidth();
var lines = $el.outerHeight() / lineHeight;
var maxWidth = $parent.width();
// top overlay
css.width = maxWidth - $el.position().left;
css.height = lineHeight;
css.top = $el.position().top;
css.left = $el.position().left;
$('<div class="overlay top"></div>').css(css).insertAfter($el);
// bottom overlay
css.width = totalWidth - css.width - ((lines-2) * maxWidth);
css.top = css.top + (lineHeight*lines);
css.left = 0;
$('<div class="overlay bottom"></div>').css(css).insertAfter($el);
// center overlay
css.width = maxWidth;
css.height = (lines- 2) * lineHeight;
// -- /needs improving -- //
}
$clone.remove();
} else {
// -- block
css.width = $el.outerWidth(true);
css.left = $el.position().left;
// -- height and top might need to improved if you want collapsing margins taken into account
css.height = $el.outerHeight(true);
css.top = $el.position().top;
// apply the styling to an overlay div and include it in the DOM
$('<div class="overlay"></div>').css(css).insertAfter($el);
}
});
}
// when the window is loaded or resized (not just ready, the images need to be there to copy their position and size)
$(window).on('load resize', function() {
// apply the overlay plugin to the body to cover all elements, or recalculate their positioning
$('body').overlayDiv();
});
そこにはたくさんのコメントがありますので、理解できると思いますが、説明が必要な場合はお気軽にお尋ねください.
ここでコードの動作を確認できます:
http://jsfiddle.net/pP96f/7/
残りの 2 つの問題について:
- 最大の問題は、複数の行にまたがるインライン要素です。要素内のテキストのみを覆いたい場合は、これを実現するために最大 3 つの個別のオーバーレイが必要になります。私は寸法 (特に下部の div の幅) に苦労していましたが、最終的にはあきらめました。任意の入力をいただければ幸いです。
- より小さな問題は、マージンの崩壊の 1 つです。これに取り組むのはそれほど難しいことではありませんが、これをどのように処理したいかわかりませんでした。(そして、私はすでにこの質問に多くの時間を費やしています...)
私の意見がお役に立てば幸いです。
編集:
親を選択してすべての子を(再帰的に)オーバーレイするだけでなく、オーバーレイする特定の要素を選択できるバージョンについては、コードのこのわずかに変更されたバージョンを見てください: http://jsfiddle.ネット/ARWBD/2/