Каскадные Таблицы Стилей

индекс
323,31

Делаем красивый fade для переполненного блока без js

Сегодня хочу рассказать об интересном способе получения такого эффекта с помощью css:

Демо



Задача:

Показывать fade только тогда, когда высота текста превышает высоту контейнера. Считается, что размеры контейнера заданы.


Решение:


Шаг первый


Для начала создадим разметку. Нам потребуются три блока:
  • для самого текста;
  • для вспомогательной распорки;
  • для fade.


<div class="text"></div>
<div class="helper"></div>
<div class="fade"></div>


Шаг второй


Основная идея состоит в том, что если два блока утекают влево (float: left), то они разместятся друг под другом, если высота промежуточного текста, в котором они плавают, больше высоты первого блока, или рядом друг с другом, если меньше. Иллюстрация:

В нашем случае утекать будут .text и .fade, а роль обтекаемого текста будет выполнять .helper.


.text {
    float: left;
    width: 400px;
}
.helper {
    height: 400px;
}
.fade {
    float: left;
    width: 400px;
    height: 60px;
    background: url(fade.png) repeat-x;
}

Высота вспомогательного элемента соответствует высоте контейнера. Тогда если .text (первый утекающий элемент) выше .helper, .fade сдвинется вправо.


Шаг третий


А теперь «инвертируем» поведение .fade путём смещения его влево на 100% ширины и вверх, чтобы он показывался в рамках контейнера:


.fade {
    ...
    margin: -60px 0px 0px -400px;
    position: relative;
}
* html .fade {
    position: static;
}

Position нужен для того, чтобы fade был сверху текста.

Шаг четвёртый


Кстати, о контейнере.


<div class="container">
    <div class="wrapper">
        <div class="text"></div>
        <div class="helper"></div>
        <div class="fade"></div>
    </div>
</div>

Обернём все элементы, чтобы дать простор их обтеканию:


.wrapper {
    width: 5000px;
    height: 100%;
}
.helper {
    height: 100%;
}

А сам контейнер сделаем таким, как хотели изначально:


.container {
    width: 400px;
    height: 400px;
    overflow: hidden;
    border: 1px solid #aaa;
}

Всё!


Демо

+62
1 апреля 2011, 14:49
159

комментарии (58)

+2
FilimoniC #
Сулит проблемы с выделением. Не смог выделить три нижних строки (если выделять начать в области этих строк).
В Хроме очень страшно выделяется, с градиентом на фоне выделения.
0
piumosso #
Ага, в хроме выделение всегда ужасное)
Всё это придумано для избавления от js-а.
+7
lahmatiy #
Добавьте pointer-events: none для .fade, тогда в Firefox и webkit'ах фейд не будет мешать выделению текста.
+1
piumosso #
спасибо
+2
Serator #
+7
ozoned #
Зачем так много кода и цсс?
Контейнеру { position: relative }, градиенту { position: absolute; bottom: 0; width: 100%; height: 60px; }
+1
piumosso #
а если текст умещается?
+1
ozoned #
Градиент будет себе висеть внизу.
+2
piumosso #
а если текст помещается ровно до упора?
последние строки будут скрыты градиентом, но это не будет корректно.
+1
ozoned #
Согласен, но в вашем случае это тоже происходит. А вот когда текста меньше — тогда да, у вас градиент «скрывается».
+2
piumosso #
как раз не происходит. фейд появляется только если текст выходит на 1 и более пикселей
0
Iverson #
Что в этом некорректного? Так же как и в вашем случае пользователь увидит один и тот же текст, и в том и в другом случае он будет знать что это весь контент который он может увидеть т.к скрола вниз нет.
0
piumosso #
какого скрола?
0
Iverson #
Который мог быть если бы вы использовали overflow: auto; вместо hidden.
0
piumosso #
вы не поняли сути задачи.
0
Iverson #
Вы не правы, я все понял, и мой вопрос был адресован как раз к самой задаче, что плохого в том что мы увидим fade если текст влезает в аккурат под размер контейнера, зачем нам вообще ставить такую задачу? А к решению у меня вопросов нет, оно работает, хоть и громоздкое.
0
piumosso #
Ну так пользователь подумает, что контент можно развернуть, кликнет, а ничего не произойдёт, только fade пропадёт
0
Iverson #
Что значит «развернуть», и куда пользователь по-вашему захочет кликнуть?
0
piumosso #
Ну вот как тут: stillion.ru/masters/10/
0
Iverson #
Что общего вы находите у блока по вашей ссылке и у того что в вашем примере? У вас кажется нет кнопки «Продолжение...», так и не понял куда пользователь по-вашему будет кликать чтобы попытаться развернуть контент.

image
0
piumosso #
Вот здесь, наверное, лучше видно stillion.ru/masters/17/
0
Iverson #
Я замучаю вас своим вопросом, уж простите)

У вас по ссылке fade кликабелен (cursor: pointer;) + в нем недвусмысленно написано «Продолжение рассказа».
Еще раз, куда и почему по-вашему пользователь будет кликать в вашем примере, если fade не кликабелен и нет никакой кнопки «Продолжение...», особенно если учесть что на большинстве сайтов fade не кликабелен а лишь является элементом дизайна?
0
piumosso #
В моём, конечно, никуда. Это плейграунд такой. Но в реальности там может быть написано что-нибудь, курсор и т.д.
+2
Glyuck #
Тогда пользователь увидит внизу градиент от белого к белому :-)
–4
VitaZheltyakov #
А что за fade.png?

Соль сей дизайнерской фишки Вы не раскрыли. Кому интересно — habrahabr.ru/blogs/personal/31284/ (в сети можно найти перевод на русском)
0
piumosso #
а при чём тут png?
речь идёт о позиционировании fade при условии выезжания текста за контейнер
–6
VitaZheltyakov #
fade — с английского обесцвечивать. В данном пример fade — это постепенное обесцвечивание блока текста. Какое отношение оно имеет к позиционированию?
+1
egorinsk #
Красивый и вроде как нестандартный пример использования флоата для выталкивания другого флоата.
0
PiSaiK #
Абсолютно не изысканный метод. ПО мне лисно удобнее так

И стили конечно
.content {
width:400px;
height:400px;
position:relative}
.fade {
background: url(fade.png) repeat-x;
height:20px;
width:100%;
position:absolute;

}
0
piumosso #
Посмотрите ещё раз задачу. Она в другом состоит. Как вы написали каждый может))
0
PiSaiK #



И стили конечно

.content {
width:400px;
height:400px;
position:relative}

.fade {
background: url(fade.png) repeat-x;
height:20px;
width:100%;
position:absolute;
bottom:0;
left:0;
right:0;
}
0
kulakowka #
Велосипедисты такие велосипедисты :) Гнать в шею дизайнеров, которые придумывают такие решения.
+2
Zume #
2 Кулаковка Идея очень юзабельна. (Например если нужно сократить заголовок)

Вопрос к автору: А градиент от белого к прозрачному наложить сверху на текст нельзя?
+3
Riz #
Я верю, однажды все браузеры будут поддерживать css3 и тогда будет достаточно написать:

-webkit-mask-image: -webkit-gradient(linear, left top, left bottom, color-stop(0, rgba(0,0,0,1)), color-stop(0.65, rgba(0,0,0,1)), color-stop(0.9, rgba(0,0,0,0)));
+1
Iverson #
Господа, о чем вы? Как это относится к данной теме?
0
dmitriid #
напрямую: nicewebtype.com/notes/2009/07/24/pure-css-text-gradient-no-pngs/

хотя градиент текст — это лишь одна из частей проблемы
0
Iverson #
Топик никак не затрагивает реализацию самого градиента, он о совершенно о другом, fade.png в данном случае мог содержать полупрозрачные облака, или дым под который плавно уходит текст, css3-градиенты тоже бы тогда относились к теме «напрямую»?
0
dmitriid #
Я как раз про такие градиенты. Задачи в топике две: сделать градинет и наложить его правильно (то есть, при каких-то граничных условиях)

Текущая реализация именно градиента вызывает проблемы в комментариях выше. Поэтому и всплыл вопрос о том, что «когда же наконец все будут поддерживать css3»
+1
piumosso #
Не, я е ставил задачу делать градиент.
Задача:
Показывать fade только тогда, когда высота текста превышает высоту контейнера.
0
dmitriid #
Ну, скажем, задача сделать fade все равно там была :) И по коду и по комментариям понятно, что лучше уж это был pure-css ;)
0
Riz #
Создание контейнера фиксированной высоты с overflow-y: hidden и строчкой что я указал решает вашу задачу. Естественно только в css3-поддерживающем браузере(с указаной строкой — конкретно в хроме).
0
kellas #
Интересная реализация, спасибо за демку, а то пока в firebug не посмотрел, понять не мог что к чему.
0
brutaler #
Я думал будет про градиент, а тут про какой-то сложный метод позиционирования на все случаи жизни.
Почему ничего не сказано в каких браузерах работает?
0
hobocta #
Проверил, работает в IE6+ и во всех современных, знакомых мне. Только для IE6, как вы несомненно знаете, нужен pngfix.
0
hobocta #
Отличное решение. Чтобы понять его пришлось напрячь мозг. Я бы решал эту задачу не без jquery.
0
kizu #
Отлично! Я как-то сделал похожую штуку, но для однострочного варианта — kizu.ru/fun/overflower/

Советую ваш пример проапгрейдить задав контейнерам (ну и всей цепочке вверх до HTML) высоту в 100%, тогда можно будет изменяя размеры окна видеть момент когда появляется градиент.
0
klierik #
image

.content {
position: relative;
max-height: 200px;
width: 200px;
padding: 10px 10px 0;

overflow: hidden;

border: 1px solid #ccc;
}
.fade {
position: absolute;
left: 0;
top: 160px;
width: 100%;
height: 50px;

background: #feffff; /* old browsers */

background: -moz-linear-gradient(top, rgba(255,255,255,0) 0%, rgba(255,255,255,.75) 50%, #FFFFFF 100%); /* firefox */
}


имхо, так и не понял зачем так изощрятся с задачей.
0
piumosso #
А если контент умещается, в вашем варианте фейд будет показываться?
0
klierik #
не будет, так как у него фикс отступ сверху (так же учтена максимальная высота).

зы: хочу заметить, но вы скорее всего увидели, решение, конечно же, не будет работать в ИЕ6
0
piumosso #
это почему не будет-то?
.fade {
position: absolute;
left: 0;
top: 160px;
width: 100%;
height: 50px;
}
всё показывается.
Смысл моего решения в том, что фейд никто не увидит, когда контента мало! И это без js.
0
klierik #
ничего подобного:

image

ведь контейнер с контентом имеет допустимую фикс высоту (сделано для гибкости)
0
piumosso #
А сделайте фон красным) Или выложите куда-нибудь «потыкать»
0
piumosso #
фон не текста, а всего документа
0
klierik #
по вашей просьбе:

klierik.com/examples/content-overflow-fade/
0
piumosso #
Ну и что? вполне возможна ситуация, когда внутреннее содержимое будет умещаться, но чуть-чуть залезать на фейд, тем самым вводя пользователя в заблуждение.
Суть задачи была именно в том, чтобы показывать фейд только когда текст выходит за рамки, а если умещается, пусть и впритык, то не показывать фейд.
0
klierik #
вот это вод чуть-чуть можно компенсировать пару пикселями отступа и это себя оправдает больше, нежели делать предложенный вами вариант который существенно сложнее(!).

ну а если вы не настроены принимать сторонние решения, которые просты и юзабельны в 99% случаев, а стараетесь всеми силами, высасывая из пальца, показать преимущества вашего решения, то текущий диалог не имеет смысла продолжать.
0
piumosso #
Есть определённая задача и вполне рабочее решение. Вы же мне предлагаете другую задачу со своим решением (которая, между прочим, достаточно проста и не заслуживала бы поста на хабре).
Согласен, смысла продолжать диалог нет.

Только зарегистрированные пользователи могут оставлять комментарии. Войдите, пожалуйста.