Использовать полную ширину, исключая полосу прокрутки переполнения с position: absolute

Я хотел бы иметь маленький красный div с полной шириной в фиксированной верхней позиции внутри другого div с overflow: scroll. Я надеюсь, что jsFiddle проясняет это: http://jsfiddle.net/mCYLm/2/.

Проблема в том, что красный div перекрывает полосу прокрутки. Я полагаю, right: 0 означает правую часть div.wrapper; он не убирает полосу прокрутки div.main. Когда я перемещаю overflow: scroll в div.wrapper, красный баннер имеет правильный размер (скрипка). Однако он больше не находится в фиксированной позиции (прокрутка вниз заставляет баннер прокручиваться вверх).

Как я могу вместе достичь двух следующих целей?

  • Красный баннер находится в фиксированной позиции, как в этой скрипке.
  • Красный баннер имеет полную ширину, за исключением полосы прокрутки, как в этой скрипке.

Я бы хотел, чтобы это работало в Google Chrome.

HTML:

<div class="wrapper">
    <div class="red-banner"></div>
    <div class="main">
        <div class="item">foo</div>
        <div class="item">foo</div>
        <div class="item">foo</div>
        <div class="item">foo</div>
    </div>
</div>​

CSS:

div.wrapper {
    position: relative;
}

div.main {
    height: 200px;
    overflow-y: scroll;
}

div.item {
    border: 1px solid black;
    margin: 20px;
    padding: 20px;
}

div.red-banner {
    background-color: red;
    position: absolute;
    left: 0;
    top: 0;
    right: 0;
    height: 20px;
}

person pimvdb    schedule 11.06.2012    source источник
comment
Почему бы просто не разместить прокручиваемый элемент под панелью? Как в этом примере. Я вижу, что это единственный простой способ сделать это.   -  person Qtax    schedule 11.06.2012
comment
В моем реальном приложении у меня есть градиент от белого к прозрачному вместо красного, чтобы иметь хороший эффект для текста, который прокручивается из контейнера. К сожалению, этот эффект невозможен, потому что баннер / контейнер разделены.   -  person pimvdb    schedule 11.06.2012
comment
@pimvdb, я вижу, думаю, тогда вас ждет рассол (если вы хотите избежать JS). Возможно, вы могли бы использовать стилизованные полосы прокрутки CSS, которые поддерживает Chrome, что, по крайней мере, дало бы вам фиксированную ширину, которую вы могли бы использовать. Или, может быть, есть какой-нибудь хороший взлом CSS3.   -  person Qtax    schedule 11.06.2012
comment
Вы можете изменить свойство right, чтобы оно соответствовало ширине полосы прокрутки ... Требуется JS, чтобы убедиться, что любая полоса прокрутки будет правильно измерена ..   -  person Gabriele Petrioli    schedule 11.06.2012
comment
@ Габи, она же Г. Петриоли: Да, это работает, спасибо. Однако это не очень приятно. Я продолжу, если не будет ответов только на CSS.   -  person pimvdb    schedule 11.06.2012


Ответы (2)


Похоже, что это невозможно с чистым CSS, поэтому вот хак JavaScript (jQuery):

$(function() {
  var $container = $("<div>").css({ height: 1, overflow: "scroll" }).appendTo("body");
  var $child = $("<div>").css({ height: 2 }).appendTo($container);
  window.SCROLLBAR_WIDTH = $container.width() - $child.width();
  $container.remove();
});

тогда:

$("div.red-banner").css({
  right: SCROLLBAR_WIDTH
});
person pimvdb    schedule 11.06.2012
comment
Не нужно использовать calc, просто установите вместо него right, right: SCROLLBAR_WIDTH + "px". - person Qtax; 11.06.2012
comment
@Qtax: Woops, я, должно быть, слишком долго смотрел на это. Спасибо! - person pimvdb; 11.06.2012
comment
@ Оба: Я принял этот ответ, потому что это было единственное решение без побочных эффектов. Я проголосовал за вас обоих; Спасибо за всю вашу помощь. - person pimvdb; 14.06.2012

HTML

<div class="scroller">
    <div class="banner-wrapper">
        <div class="banner"></div>
    </div>
</div>

<div class="main">
    <div class="item">foo</div>
    <div class="item">foo</div>
    <div class="item">foo</div>
    <div class="item">foo</div>
</div>​

CSS

* { margin: 0; padding: 0 }
body {
    padding-top: 30px;
}

div.main {
    height: 200px;
    width: 100%;
    overflow-y: scroll;
    position: absolute;
    z-index: 50;
    background: -webkit-gradient(linear, center top, center bottom, from(white), to(rgba(255,255,255,0)));
}

div.item {
    border: 1px solid black;
    margin: 20px;
    padding: 20px;
}

div.scroller {
    height: 20px;
    width: 100%;
    position: absolute;
    z-index: 100;
    overflow: hidden;
}

div.banner-wrapper {
    background: transparent;
    position: relative;
    height: 20px;
    overflow-y: scroll;
    left: 0;
    margin-right: -20px;
}
div.banner {
    height: 20px;
    background: -webkit-gradient(linear, center top, center bottom, from(white), to(rgba(255,255,255,0)));;
    margin-left: 20px;
    margin-right: 40px;
}

Версия для разработки: http://jsfiddle.net/mCYLm/13/
Окончательная версия: http://jsfiddle.net/mCYLm/14/

Работает с масштабированием и изменяемой шириной области просмотра.
! ОШИБКА: кнопка полосы прокрутки справа вверху недоступна / недоступна.

Проверено в:

  • IE6,7,8,9 (окна)
  • FF11 (Windows)
  • Google Chrome 18 (убунту)
  • Safari 5.1 (OSX)
person doptrois    schedule 11.06.2012
comment
Большое спасибо, но теперь текст перекрывает баннер. Идея заключалась в том, чтобы вместо этого баннер перекрывал текст (как в скрипке). Вы бы знали, возможно ли это? - person pimvdb; 11.06.2012
comment
Это не исправляет, а просто помещает прокручиваемый элемент на полосу. - person Qtax; 11.06.2012
comment
@pimvdb Итак, наконец, единственное решение CSS: jsfiddle.net/mCYLm/9. Теперь я отредактирую свой ответ, добавив новую информацию о том, как его использовать. Возможно, вам потребуется заменить DataURI в соответствии с вашими потребностями. - person doptrois; 11.06.2012
comment
Да спасибо! Я использую -webkit-gradient, который отлично работает, если я вставлю его в ваш код: jsfiddle.net/mCYLm/10. Это требует жесткого кодирования ширины баннера, ну да ладно. - person pimvdb; 11.06.2012
comment
@pimvdb Круто! Это делает меня счастливым! Он должен работать и с переменной шириной, я узнаю завтра. - person doptrois; 11.06.2012
comment
@pimvdb, который работает правильно, только вы знаете ширину как содержимого, так и полосы прокрутки. Попробуйте увеличить масштаб (нажмите CTRL + PLUS ~ 5 раз), и вы увидите, что затухание не покрывает правую границу элементов. И если вы просто знаете ширину полосы прокрутки, вы можете просто изменить значение right исходного CSS, чтобы оно соответствовало ширине полосы прокрутки. - person Qtax; 11.06.2012
comment
@Qtax: Хм, да, это так. Я опубликую свой хак JavaScript, который использую сейчас. @ dop-trois: Извините за отказ, но в противном случае все подумают, что вопрос решен. - person pimvdb; 11.06.2012
comment
@ dop-trois, это решение не может быть идеальным, поскольку оно зависит от ширины полосы прокрутки. Но если это нормально для OP, тогда все в порядке. - person Qtax; 11.06.2012
comment
@Qtax Простите за это, протестировал сейчас, как и вы, я радовался слишком рано: P @ pimvdb: нет проблем. - person doptrois; 11.06.2012
comment
@Qtax Теперь работаем с масштабированием и переменной шириной (в процентах). Что об этом? jsfiddle.net/mCYLm/14 - person doptrois; 11.06.2012
comment
@pimvdb Теперь работаем с масштабированием и переменной шириной (в процентах). Что об этом? jsfiddle.net/mCYLm/14 Извините, не могу выбросить это из головы;) - person doptrois; 11.06.2012
comment
@ dop-trois: Спасибо за вашу помощь! Однако на этот раз полоса прокрутки по-прежнему не работает. Визуально ничто не перекрывает полосу прокрутки, но стрелку вверх невозможно щелкнуть. Вот почему я хотел избежать перекрытия :) - person pimvdb; 12.06.2012
comment
@pimvdb Хорошо ^^. Кажется, действительно невозможно получить это 100% без ошибок :) Спасибо за ваш ответ. - person doptrois; 12.06.2012