CSS: дочерний div, перекрывающий родительский элемент

У меня примерно следующее:

<div id="body">
  surrounding text 
  <div id="pane" style="overflow: auto; height: 500px; width: 500px;">
    lots and lots of text here
    <span id="some_bit">tooltip appears below-right of here</span>
  </div>
  more surrounding text (should be overlapped by tooltip)
</div>

а также:

<div id="tooltip" style="width: 100px; height: 100px;">Whee</div>

Я хочу вставить всплывающую подсказку так, чтобы она располагалась над панелью, в которой она находится. Если она прикреплена к элементу, который находится рядом с границей панели (как указано выше), то она должна быть видна выше панель и над текстом, окружающим панель.

Он НЕ должен а) расширять панель, так что вам нужно прокрутить вниз, чтобы увидеть всплывающую подсказку (например, в http://saizai.com/css_overlap.png) или б) быть обрезанными, чтобы вы не могли видеть всю подсказку.

Я вставляю это с помощью JS, поэтому при необходимости я могу добавить оболочку position:relative div или тому подобное, вычислить смещения и сделать его position:absolute и т. Д. Я бы предпочел ничего не предполагать о свойстве панели position - всплывающая подсказка должна быть вставлена ​​с помощью минимальные предположения о возможном макете страницы. (Это всего лишь один пример.)

Я пишу для прототипа библиотеки всплывающих подсказок с открытым исходным кодом.

Расчетное время прибытия: http://jsfiddle.net/vCb2y/5/ ведет себя визуально как я хочу (если вы продолжаете повторно наводить курсор на текст триггера), но мне потребуется обновить положение всплывающей подсказки при всех изменениях DOM и поведении прокрутки. Я бы предпочел, чтобы всплывающая подсказка была размещена с использованием чистого CSS / HTML, чтобы она имела такое же визуальное поведение (т.е. она перекрывала все другие элементы), но оставалась в своем положении относительно цели при изменении DOM, прокрутки, и т.п.

Расчетное время прибытия 2: http://tjkdesign.com/articles/z-index/teach_yourself_how_elements_stack.asp (оставьте значения по умолчанию, за исключением установки голубого div 'a' на position: relative; представьте, что «A» - это панель, а «a» - всплывающая подсказка), кажется, ведет себя более точно так, как я хочу, но я не смог заставить его работать в другом месте. Обратите внимание, что если вы сделаете «А» overflow: auto, это нарушит перекрывающееся поведение «а».


person Sai    schedule 04.07.2010    source источник
comment
Привет, Сай, мне сложно представить себе это в голове. Есть ли шанс, что у вас есть дизайн или набросок для него?   -  person Marko    schedule 05.07.2010
comment
Марко: saizai.com/css_overlap.png   -  person Sai    schedule 05.07.2010


Ответы (3)


Я не могу придумать для этого чисто HTML / CSS-решение.

Проблема здесь в объявлении переполнения. Если всплывающая подсказка находится в #pane:

  1. вы устанавливаете контекст позиционирования в #pane, тогда всплывающая подсказка отображается рядом с #some_bit (независимо от прокрутки и т. д.), но она обрезается.

  2. вы не устанавливаете контекст позиционирования, тогда всплывающая подсказка не обрезается, но не имеет понятия, где находится #some_bit на странице.

Боюсь, вам понадобится JS, чтобы отслеживать, где на странице находится #some_bit, и соответствующим образом размещать всплывающую подсказку. Вам также нужно будет отключить эту всплывающую подсказку, как только #some_bit окажется за пределами области просмотра (не проблема, если триггер наведен мышкой).

На самом деле, если триггер наведен мышкой, вы можете использовать координаты курсора для позиционирования всплывающей подсказки (вместо вычисления позиции #some_bit).

person Thierry Koblentz    schedule 05.07.2010
comment
Спасибо за ответ. Я как бы надеялся, что будет способ прикрепить что-то к нему, чтобы он не разделял контекст, но все равно отслеживал свое положение. Вздох. - person Sai; 06.07.2010

Я бы просто поместил всплывающую подсказку за пределы #pane div и разместил ее абсолютно с использованием JavaScript, поскольку вы все равно используете JS.

Я не использую Prototype, поэтому не знаю, как это делается в Prototype, но в jQuery вы должны использовать $(element).position() для получения позиции элемента. Если вам нужно сделать это вручную, это немного сложнее.

И вы, вероятно, захотите добавить немного дополнительной логики, чтобы всплывающая подсказка не выходила за пределы документа.

person Lèse majesté    schedule 04.07.2010
comment
AFAICT, проблема в том, что если прокрутить #pane, положение точки присоединения изменится (относительно области просмотра и документа), и мне придется ее переместить. Это означает мониторинг прокрутки, что вносит значительную сложность, которую я бы предпочел избежать, если это возможно. - person Sai; 05.07.2010
comment
Неплохо подмечено. И мне было бы интересно какое-нибудь решение на чистом CSS / HTML, но я не уверен, что оно есть. - person Lèse majesté; 05.07.2010

Изменить: используется CSS

#tooltip {
    z-index: 9999;
    display: none;
    position: absolute;
}

Используется JS

Примечание: в jQuery, но его должно быть легко изменить на синтаксис прототипа.

$('#some_bit').hover(function() {
    var docViewTop = $(window).scrollTop();
    var docViewBottom = docViewTop + $(window).height();

    // hovered element
    var offset = $(this).offset();
    var top = offset.top + docViewTop;
    var left = offset.left;
    var width = $(this).width();
    var height = $(this).height();
    var right = left + width;
    var bottom = top + height;

    // pane
    var poffset = $('#pane').offset();
    var ptop = poffset.top + docViewTop;
    var pleft = poffset.left;
    var pwidth = $('#pane').width();
    var pheight = $('#pane').height();
    var pright = pleft + pwidth;
    var pbottom = ptop + pheight;

    // tooltip
    var ttop = bottom;
    var tleft = right;
    var twidth = $('#tooltip').width();
    var theight = $('#tooltip').height();
    var tright = tleft + twidth;
    var tbottom = ttop + theight;

    if (tright > pright)
        tleft = pright - twidth;
    if (tbottom > pbottom)
        ttop = pbottom - theight;
    if (tbottom > docViewBottom)
        ttop = docViewBottom - theight;
    $('#tooltip').offset({top: ttop, left: tleft});
    $('#tooltip').css('display', 'block');
}, function() {
    $('#tooltip').hide();    
});

Изменить: см. здесь.

person melhosseiny    schedule 04.07.2010
comment
Этот пример не работает. См. jsfiddle.net/DTBBt/1, где я действительно добавил много текста туда, где говорится. У вас есть всплывающая подсказка для вставки в проблему с прокручиваемой областью, как и на моем изображении. - person Sai; 05.07.2010
comment
В чем причина использования диапазона для включения всплывающей подсказки? Он в основном используется как элемент блочного уровня, верно? - person Lèse majesté; 05.07.2010
comment
Использование диапазона делает HTML действительным. - person melhosseiny; 05.07.2010
comment
DIV могут быть вложенными AFAIK. Единственное, что вам не разрешено делать в действительном HTML-документе, - это встраивать элементы уровня блока внутри встроенных элементов. - person Lèse majesté; 05.07.2010
comment
Да, но я не думаю, что он хочет заключить всплывающую подсказку в div. - person melhosseiny; 05.07.2010
comment
Но это то, к чему я клоню. Если вы собираетесь визуализировать SPAN как блочный элемент, тогда почему предпочтение SPAN над DIV? Это семантическая проблема? - person Lèse majesté; 05.07.2010
comment
Но я только изменяю его свойство отображения с помощью CSS, документ HTML все еще действителен. Если вы используете элемент div, он не будет проверяться. Кстати, извини, Сай. Я не сразу понял вашу проблему. Скорее всего, вам придется рассчитать его позицию, используя JS, как упоминал Лез. - person melhosseiny; 05.07.2010
comment
Ах, моя ошибка. Я не заметил, что #some_bit тоже был SPAN. - person Lèse majesté; 05.07.2010
comment
Для моего использования #some_bit совершенно произвольно. На самом деле это может быть span, img, div - что угодно. Всплывающая подсказка должна поддерживать прикрепление к любому произвольному элементу. - person Sai; 05.07.2010
comment
mel: Ваш код по-прежнему ведет себя не так, как мне нужно. См. jsfiddle.net/vCb2y/2. Всплывающие подсказки, которые я использую, запускаются не только при наведении курсора мыши. , и они не обязательно привязаны к панели. Я это прокомментировал. Другая проблема заключается в том, что при прокрутке панели всплывающая подсказка не прокручивается вместе с ней. Вы можете захватить прокрутку и изменить положение в JS, но это путаница; Я бы предпочел, чтобы он вел себя естественно как часть DOM. - person Sai; 05.07.2010
comment
mel: у этого объекта нет подсказки, даже неопределенно прикрепленной к его цели; он просто закреплен внизу. (Сделать position: absolute тоже не работает.) - person Sai; 05.07.2010
comment
Почему здесь работает: tjkdesign.com/articles/z-index/ ? Просто сделайте голубой один родственником, и он будет поверх зеленого - в основном то, что я хочу. Но когда я пытаюсь воспроизвести, это, похоже, не работает. - person Sai; 05.07.2010
comment
Вы имеете в виду, что действительно хотите, чтобы всплывающая подсказка перекрывала окно браузера? Потому что, если всплывающая подсказка прикреплена к нижнему правому краю элемента и вы прокручиваете, она должна либо прокручиваться вне поля зрения, либо просто придерживаться края браузера, на который она попадает. - person melhosseiny; 05.07.2010
comment
mel: Это тоже не совсем работает - попробуйте прокрутить либо красное, либо белое окно (намеренно оба достаточно длинные, чтобы запускать полосы прокрутки). Всплывающее окно остается на месте, а не отслеживает цель. - person Sai; 05.07.2010
comment
Мудрое поведение: я хочу, чтобы всплывающая подсказка была выше ВСЕГО. Всегда. При желании я ограничу его определенными границами (например, окном просмотра или панелью), но это необязательно. По умолчанию это перекрытие. - person Sai; 05.07.2010
comment
У вас никогда не может быть элемента, перекрывающего браузер. Что же именно вы хотите, чтобы в случае прокрутки всплывала подсказка при прокрутке панели? А также что должно произойти при прокрутке окна просмотра? - person melhosseiny; 05.07.2010
comment
... так что в основном ваша текущая версия такая же, как и у LM выше. Оба не справляются с прокруткой или другим изменением контекста. Если бы это была всплывающая подсказка, привязанная к мышке, все было бы хорошо - я бы все равно обновил ее при mousemove. Но для всплывающей подсказки, привязанной к элементу, я хочу, чтобы она всегда следовала за элементом - желательно с помощью CSS, а не отслеживать все изменения DOM и перемещать его самостоятельно. - person Sai; 05.07.2010
comment
Если он не привязан к области просмотра (это отдельная логика), он должен оставаться относительным к элементам. То есть, если указано, что он должен быть на 5 пикселей вниз и вправо от целевого элемента, то это все равно должно быть верно после прокрутки. Если этого места нет в области просмотра, то всплывающая подсказка, привязанная к элементу, также не отображается. - person Sai; 05.07.2010
comment
В принципе, мне нужно визуальное поведение, которое он имеет сейчас (игнорируя бит границы окна просмотра), но без необходимости обновлять его положение с помощью JS при каждом изменении DOM, прокручивании окна просмотра или панели и т. Д. - person Sai; 05.07.2010
comment
Проблема в том, что если вы поместите всплывающую подсказку внутри переполненной панели (так, чтобы ее можно было расположить относительно элемента), вы никогда не сможете сделать так, чтобы она перекрывала панель. А если вы вынесете его на улицу и разместите абсолютно точно, вы никогда не сможете отслеживать прокрутку панели без JS. - person melhosseiny; 05.07.2010
comment
Мел: Это действительно проблема. ;-) Конечно, есть способ обойти это ограничение? - person Sai; 05.07.2010
comment
Я не боюсь. Это все, что касается позиционирования CSS. - person melhosseiny; 05.07.2010