Эффект отражения
Задача
Добавить эффект отражения текстовому элементу. Главное требование — гибкость, т.е. текст может меняться, эффект соответственно подстраиваться.
Решение-мечта
Упомяну сразу про CSS свойство, специально для этого предназначенное — -webkit-box-reflect. Пишем подобное правило:
.reflect { -webkit-box-reflect: below 0 -webkit-gradient(linear, left top, left bottom, from(transparent), color-stop(0.5, transparent), to(white)); }
и получаем нужный эффект. При чем данное свойство применимо как к тексту, так и к любым другим элементам, в включая изображения (<video> не пробовал). Не нужно беспокоится на каком фоне расположен элемент: отражение создается полупрозрачным. Единственный и серьезный минус данного решения — отсутствие кроссбраузерности: данное свойство поддерживают только webkit браузеры.
Решение-реальность
Чтобы добиться аналогичного результата кроссбраузерно, придется добавить атрибуты в HTML, воспользоваться псевдо элементами :after и :before, CSS правилами для трансформаций и градиентов:
<h1 title="Xiper - пример CSS отражения" class="h1-css">Xiper - пример CSS отражения</h1>
.h1-css { color: #000066; font-size: 24px; margin-bottom: 30px; position: relative; /* элемент к которому применяем эффект должен быть блочным и position: relative */ } .h1-css:after { /* получаем копию оригинального текста в перевернутом виде */ content: attr(title); /* оказывается в CSS и так можно - извлечь значение атрибута */ position: absolute; /* отражение позиционируется относительно родителя */ left: 0; top: 100%; /* можно управлять удаленностью отражения. 100% - отражение вплотную */ width: 100%; height: 100%; -moz-transform: scaleY(-1); /* много правил для CSS переворота */ -o-transform: scaleY(-1); -webkit-transform: scaleY(-1); -ms-transform: scaleY(-1); transform: scaleY(-1); z-index: 1; /* чтобы отражение можно было перекрыть */ } .h1-css:before { /* создаем эффект затухания */ content: ""; display: block; width: 100%; height: 80%; /* подбирается в зависимости о того какой процент отражения должен быть виден */ background:-moz-linear-gradient(top, rgba(255,255,255,0.7), rgba(255,255,255,1)); /* много правил для линейного градиента */ background: -o-linear-gradient(top, rgba(255,255,255,0.7), rgba(255,255,255,1)); background: -webkit-gradient(linear, left top, left bottom, from(rgba(255,255,255,0.7)), to(rgba(255,255,255,1))); position: absolute; left: 0; top: 110%; /* подбирается в зависимости от необходимого эффекта затухания */ z-index: 2; / чтобы перекрыть перевернутый текст */ }
Атрибут в HTML хоть и очень не хочется, но приходится добавлять, т.к. правило content не способно прочитать текст элемента.
А что же IE?
С IE есть целый ряд проблем даже если не считаться с IE6:
- CSS переворот (transform) IE вплоть до 9-й версии не поддерживает. Но зато имеется CSS фильтр для переворота flipV.
- CSS градиенты тоже отсутствуют включая 9-ю версию, но зато есть фильтр Alpha.
- IE7 не поддерживает псевдо элементы. Правда это можно решить с помощью expression.
- в IE8-9 нельзя применить фильтры к пседоэлементам, т.к. последние применяются только к элементам, имеющие layout.
- IE8-9 не поддерживает expression.
В итоге для IE7 можно написать CSS правила используя expression и фильтры которые тоже создадут эффект отражения. А вот IE8 и IE9, хотя браузеры и по новее, единственным преимуществом в данном случае перед IE7 оказалась поддержка псевдоэлементов. Ну и в данном случае с этой поддержи толку нет, т.к. нельзя к ним применить фильтры. И создать элементы в CSS тоже уже нельзя. Поэтому для них пришлось писать небольшой скрипт. Т.к. IE7 использует ту же технику, его тоже сюда включил. Меню — один из наиболее часто используемых компонентов сайта, для которого есть соблазн создать такой эффект. Поэтому его включил в этот пример:
<!--[if lte IE 9]> <style> .h1-after, .menu-css { position:absolute; left:0; top:100%; z-index: 1; background: #fff; -ms-filter: "flipV progid:DXImageTransform.Microsoft.Alpha(opacity=50, style=1, finishOpacity=0, startx=0, starty=0, finishx=0, finishy=70)"; /* для IE8-9 */ filter: flipV progid:DXImageTransform.Microsoft.Alpha(opacity=50, style=1, finishOpacity=0, startx=0, starty=0, finishx=0, finishy=70); /* для IE7 */ } .h1-css:after, .menu-css a:after { display: none; /* для IE8-9 прячем контент псевдоэлемента */ } </style> <script> textReflect = function() { // отражение для заголовка var el = document.getElementsByTagName("h1")[0]; el.insertAdjacentHTML("afterBegin", "<span class=&h1-after&>"+el.firstChild.nodeValue+"</span>"); // отражения для меню var menu = document.getElementsByTagName("a"), i, lenMenu = menu.length; for(i=0;i<lenMenu;i++) menu[i].insertAdjacentHTML("afterBegin", "<span class=&menu-after&>"+menu[i].firstChild.nodeValue+"</span>"); } window.onload=textReflect; </script> <![endif]-->
Смотрим демо пример. Проверено в:
- IE 6-8
- Firefox 4
- Opera 11
- Safari 5
- Chrome
Недостатки
- дополнительный атрибут в HTML;
- раздутый CSS;
- не подходит для неоднородного фона;
- нет поддержки Opera 10 и IE6 (кому это нужно?);
- Javascript для IE.
Итого
Решение вышло отдаленно напоминающее боевой вариант. Хотя в некоторых случаях может пригодится. А в целом вариант больше теоретический, нежели практический.