Пользователь
0,0
рейтинг
26 января 2013 в 03:13

Разработка → Cпойлер средствами css… tutorial

В предпраздничные дни выдалась минутка, захотелось отвлечься — окунуться в мир занятных идей, отстранясь от забот праздника. В итоге, — идея: не ожидая пришествия html5, — смастерить спойлер «по клику» посредством css и HTML.



Ранее в инете делались попытки реализовать подобное через псевдоклассы, — в основном через :focus, что вело к самоскрытию контейнера, при потере фокуса.
Основа данной конструкции — псевдокласс :checked

Минималистически идея выглядит так:

     /* CSS */
.spoiler >  input + .box {
	display: none;
}
.spoiler >  input:checked + .box {
	display: block;
}

<!--// HTML //-->
<div class="spoiler">

     <input type="checkbox" >
     <div class="box">

           Текст сообщения в спойлере.

     </div>

</div>


Как видим получился кроссбраузерный код, начиная с ИЕ9, где уже есть псевдокласс «:checked» и кончая актуальными версиями остальных браузеров. Cогласно замыслу, — это «чистая» html-css реализация.

При попытках расширить действие на ИЕ6-8, (тут, как обычно для ие,- «чистота» реализации теряется), и мы подключаем гугловскую библиотеку псевдоклассов для ИЕ:

<!-- Compliance patch for Microsoft browsers -->
 <!--[if lt IE 9]><script src="http://ie7-js.googlecode.com/svn/trunk/lib/IE9.js"></script><![endif]-->

Под катом итоговый код «танцев c кроссбраузерностью» *тестировалось в ХP, Win7-8*
<!DOCTYPE>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=windows-1251" />
<title>Cпойлер средствами css</title>

<style>
.spoiler >  input + .box > blockquote{
	display: none;
}
.spoiler >  input:checked + .box > blockquote {
	display: block;
}
.spoiler >  input[type="checkbox"] {
	cursor: pointer;
	border-color:transparent!important;
	border-style:none!important;
	background:transparent none!important;
	position:relative;z-index:1;
	margin:-10px 0 -30px -230px;
 }
.spoiler >  input[type="checkbox"]:focus {
	outline:none;	/* Убираем обводку в ИЕ8 при "фокусе" */
}
.spoiler span.close,
.spoiler span.open{
	padding-left:22px;
	color: #00f!important;
	text-decoration: underline;
}
.spoiler >  input +  .box > span.close {
	display: none;
}
.spoiler >  input:checked +  .box > span.close {
	background: url(http://st0.bbcorp.ru/img/minus.png) 4px 60% no-repeat;
	display: inline;
}
.spoiler >  input:checked  + .box > span.open {
	display: none;
}
.spoiler >  input +  .box >  span.open {
	background: url(http://st0.bbcorp.ru/img/plus.png) 4px  60% no-repeat;
	display: inline;
}
.spoiler blockquote,
.spoiler{
    padding:1em;
    border-radius:15px;
    -webkit-border-radius:15px;
    -khtml-border-radius:15px;
    -moz-border-radius:15px;
    -o-border-radius:15px;
    -ms-border-radius:15px;
}
.spoiler {
    overflow-x:hidden;
    box-shadow: 0px 3px 8px #808080;
    border:#E5E5E5 solid 2px;
    -webkit-box-shadow:0px 3px 8px #808080;
    -khtml-box-shadow:0px 3px 8px #808080;
    -moz-box-shadow:0px 3px 8px #808080;
    -ms-box-shadow:0px 3px 8px #808080;
}
.spoiler blockquote {
   margin-top:12px;
   min-height: 23px;
   border:#CDCDCD 2px dashed;
}
</style>

<!-- Compliance patch for Microsoft browsers -->
 <!--[if lt IE 9]><script src="http://ie7-js.googlecode.com/svn/trunk/lib/IE9.js"></script><![endif]-->
</head>

<body>
           <div id="wrap" style="padding:200px 40px;width:70%;margin:0 auto;background-color:#fff;height:100%">


<div class="spoiler">

<!--* Добавлен tabindex="-1" для снятия фокуса при переходе по "tab" -->
<input style="width:360px;height:45px;" type="checkbox" tabindex="-1" >
     <div class="box">
         <span class=close>Скрыть</span><span class=open>Показать</span>
         <blockquote class="Untext">
Lorem Ipsum is simply dummy text of the printing and typesetting industry.
         </blockquote>
     </div>

 </div>

          </div>
</body>
</html>
Минусы:
В ИЕ8 — наличествует пунктирная обводка чекит-бокса при фокусе;// fixed (подсказка от fcunited )
в ИЕ6-7 — чекит панель «винтажно» выдвинута левее спойлера; (Но мы и не ставили себе задачу поддержку данных Ие в изначальных замыслах.

DEMO


PS: Код позволяет просматривать контент спойлера при отключённом java-script, — что востребовано при серфе со старых мобильников, анонимайзеров или с жестко-настроенных фаерволов.
Хочу выразить признательность Octane с javascript.ru форума и devote, без которых идея не могла быть реализованной.
@Defff
карма
16,0
рейтинг 0,0
Пользователь
Реклама помогает поддерживать и развивать наши сервисы

Подробнее
Реклама

Самое читаемое Разработка

Комментарии (65)

  • +4
    Добавьте, так кошернее будет
    .spoiler > input[type=«checkbox»] {
    cursor: pointer;
    }
  • 0
    Carduelis, сенкс
  • +4
    На мой взгляд, такие решения на псевдо-классах вроде :cheched — большой хак. Подобная задача, как я писал, решается в несколько строчек на javascript, и такое решение работает во всех браузерах. Псевдо-класс :checked предназначен для оформления форм, а именно настоящих переключателей.

    Здесь же вставляются лишние элементы ради сомнительной цели. Нарушается семантика, появляется лишняя точка фокуса (хоть бы tabindex="-1" приписали), CSS-код сильно раздут и зависит от структуры HTML, которая неочевидна для тех, кто может потом попытаться его использовать. «Чистым» такой код невозможно назвать.
    • +1
      Не всегда. Например, когда мы хотим сделать текст правее чекбокса другого цвета, то тут этот псевдокласс незаменим.

      label span {color: #ccc;}
      label input:checked + span {color: #333;}

      Когда мы нажали — текст черный, иначе серый
      • +2
        Я и написал: «псевдо-класс :checked предназначен для оформления форм, а именно настоящих переключателей.»
    • 0
      Aingis:,«Чистым» такой код невозможно назвать
      «Чистым» был назван согласно замыслам статьи использовать только теги HTML и css. Вчитывайтесь в замысел топика, иначе минусы за мои вкусы зимой — как то авторитарно!
      • +5
        Замысел-то и сомнителен. Зачем использовать средства оформления: HTML и CSS для решения задачи поведения, что выполняется средствами Javascript?
        • –1
          Жизнь вообще штука сомнительная, а что то делать в ней, — тем паче, обязательно спросят — Зачем живешь?
          Aingis? Собственно разные выключалки на ява-скрипт много делал, Вашу видел тоже, — неплохо, — но мне захотелось разнообразия, Имхо тут, мне кажется, в полемике, именно ваша работа, реагирующая на «фокус на элементе даёт о себе знать.
      • +1
        Дело даже не во вкусах, а в том, что ваш метод, 1) сам по себе хак, 2) требует использовать хак для поддержки старых версий IE, 3) не во всех современных браузерах работает.
        • 0
          идея: не ожидая пришествия html5, — смастерить спойлер «по клику» посредством css и HTML
        • –1
          Kolonist,« а в том, что ваш метод, 1) сам по себе хак,»
          С чего вдруг — Хак? Или сss вида: input:checked + elem недопустимо в какой-либо спецификации?
          Исходный минималистический код работает во всех браузерах поддерживающих псевдокласс :checked
          Весь нюанс более полного кода, — это подвижка input под левый край .spoiler , скрытого overflow-x: hidden, (дабы не было видно окно чекита). Если не стремится к экстремальному скрытию окна чекита, никаких нюансов и нарушений — нет!
    • 0
      Aingis,-«Здесь же вставляются лишние элементы ради сомнительной цели. Нарушается семантика»
      Не убедительно, — укажи на эти лишние элементы?

      Вот разница в css, по сравнению с типовым ява-скрипт спойлером такого же дизайна
      .spoiler >  input + .box > blockquote{
          display: none;
      }
      .spoiler >  input:checked + .box > blockquote {
          display: block;
      }
      

      При обычном спойлере эти строки типично заменяются на:
      .spoiler > .box > blockquote{
          display: none;
      }
      .spoiler.active > .box > blockquote {
          display: block;
      }
      

      Aingis, — «и зависит от структуры HTML»
      Приведите примеры. Код достаточно гибок к структуре окружения,
      Моим примером может послужить работа вложенных cпойлеров: Ссылка
      • +1
        Пожалуйста. Лишний элемент, очевидно, <input type="checkbox">. С какого рожна тут чекбокс? Правильно, чтобы присобачить :checked не по назначению. И он тут обязательно нужен, что может быть не очевидно, не знакомому с трюком, человеку. Он должен быть обязательно перед скрывающимся блоком, чтобы сработал селектор „+“.
        При использовании javascript с базовыми стилями из моей статьи «Простой универсальный переключатель на JavaScript» дополнительных стилей вообще не требуется, достаточно использовать стандартные классы в HTML:
        <div class="spoiler jsw">
            <span class="open jst jseh">Показать</span>
            <span class="close jst jsh jseb">Скрыть</span>
            <blockquote class="box jsh jseb">
                Содержание «спойлера»
            </blockquote>
        </div>
        

        Хотя желательно, чтобы без JS были скрыты дополнительные элементы «Показать» и «Скрыть», просто показывалось содержимое спойлера. (Или как вариант можно сделать ссылки, которые будут раскрывать с помощью простановки соответствующих классов со стороны сервера, но это слишком громоздко, на мой взгляд.) Классы spoiler, open, close и box я добавил для понятности, они вовсе не нужны для реализации.

        Можно модифицировать структуру HTML как угодно, это никак не повлияет на работоспособность. (Разумеется, открывающей элемент должен быть вне скрытой части спойлера.)
        • 0
          Aingis, я не против javascrip. Неужели не забавно решать неординарные задачки?
          Если б у меня было желание делать в новый код скриптом… когда весь год только в скриптах и сижу…
          И я не навязываю никому свою идею, — вот захотелось сделать,- покрутил — получилось, а потребуется — нет — Ваше дело.
          Это как шахматная партия, — интересно и всё. А нужность — дело личных предрасположений и оценок, не так ли?
        • 0
          С какого рожна тут чекбокс?
          Хм, — вспомним, что в эпоху Аякса — чекиты, селекты и input(ы) всех марок — можно увидеть разбросанными по странице, согласно удобству интерфейса, а отсылается — собирается все через FormData и отправляется Аяксом.
          чтобы присобачить :checked не по назначению
          Опять проводка собственного мнения, — есть спецификация! В которой оглашено применение псевдоклассов. Запреты — не аргументированы
          • 0
            Только когда они реально что-то меняют. Здесь он меняет только внешний вид. Ajax тут не причём. Не вяжется.
            • 0
              Aingis, еще раз :
              идея: не ожидая пришествия html5, — смастерить спойлер «по клику» посредством css и HTML
              Поскольку не загорами => details htmlbook.ru/html/details
              Пока доступный только в Хроме, вот данный эксперимент на подключение-пробы к переходу текущих браузеров.
              • 0
                В HTML5 включено много паттернов, в том числе динамических. Есть даже такой элемент как <output>. Только — вот сюрприз! — без включённого Javascript он бесполезен.
          • НЛО прилетело и опубликовало эту надпись здесь
            • 0
              не по назначению используется сам HTML-элемент input
              Зачитайте пожалуста список назначений для чекита? К примеру на стандатных шаблонах форуиа чекит вне формы стоит для скрипта транслита — переводит — не переводить вввод текста — т.е для скрипта(транслита) — это по назначению — для свойства сss cпойлера — нет. Аргументы могут быть лишь одни — спецификация, и предупреждения о багах производителей браузеров. Да и потом, все эти вещи и скрипты и сss для данного применения временны, грядущее HTML5 даёт нам уже тег спойлера с автоматикой. Данная версия лишь отработка сss замены, когда заъочется подключить к контейнеру скрытия плавность хода, скругления и иные диз наработки, поскольку в текущее время они выполнялись по большей части скриптом(Возьмите плавность спойлера на Хабре, а уже 'завтра' css нужно будет адаптировать к details.)
              • 0
                SelenIT2. Потом, что Вы мне говорите — «не по назначению используется сам HTML-элемент input»
                Кнопка input изначально используется для скрытия/открытия спойлеров! (Давайте теперь спорить за type
                Так что аргументы излишества или не по назначению — не убедительны, -существует куча спойлеров с кнопкой инпут, значит спор только за тип — а чем хуже чекит нежели буттон?
                • 0
                  который, к тому же, может закешироваться и ненавязчиво использоваться повторно в куче мест),
                  Хитро улыбаясь, — а что, сss файл намного хуже кешируется? 2. Скрипты создают бо'льшую нагрузку на браузер, нежели сss. 3-е и решающее, делал я вещицу для себя, — понравился ход решения и показался занятным. Поэтому выложил, посколь задачка интересная.
                  Собственно задачка, -внутренний призыв к читателю, — попробуйте сделать лучше(сложить кубик рубика, — это занимательные задачки Перельмана -./.конечно если есть время и интерес./
                  • 0
                    Да что вы так заводитесь?
                    Всем же понятно, что делалось для фана.
                    Практическая ценность решения нулевая, если не отрицательная, но сам факт понимания того, что можно сделать и так, достаточно ценен.
                    Нагрузка на браузер? От скрипта, добавляющего всего лишь одно свойство одному элементу? Да «в эпоху Аякса» (ваши же слова)? Да вы лукавите.
                    Хороший эксперимент. Хорошая демонстрация возможностей css. Разминка для мозга — всё здорово. Поймёт не каждый, но кому интересно, тот поймёт и оценит.
                    Просто не надо это решение позиционировать как практическое, и не надо удивляться, когда его таковым не воспринимают.
                    • 0
                      Зря на демагогию ведётесь.
                      • 0
                        да ну при чём тут демагогия?
                        Всё же очевидно. Автор нашёл интересную возможность, поделился на хабре, рассчитывая на то, что местное население оценит тоже. Тоже понятно: хабр вроде как позиционируется как сообщество айтишников — людей, двигающих прогресс вперёд.
                        А тут вдруг взяли и обругали.
                        Признаться честно, я такого рода открытия тоже время от времени делаю, но публиковаться не хватает духа как раз из-за того, что вот точно так же обругать могут, что это большинству читателей неинтересно будет.
                        • НЛО прилетело и опубликовало эту надпись здесь
                    • 0
                      Просто не надо это решение позиционировать как практическое
                      Ну начало cтатьи точно соответствует кино: — 31декабря «Мы все вместе ходим в баню», и далее описание короткого приключения, а тут завелось как-то по- серьезному, хотя аргументы — слабые.
                      «Нагрузка на браузер? От скрипта, добавляющего всего лишь одно свойство одному элементу? » — «Нагрузка от чекита, той же длины что кнопка input во многих спойлерах? „

                      Спасибо, что поняли про задачку разминка для мозга… Просто топик завёл… уже инерция, пойду спать, Вам, — удачи в новом дне.
                  • НЛО прилетело и опубликовало эту надпись здесь
                • НЛО прилетело и опубликовало эту надпись здесь
            • 0
              SelenIT2, Возможно, в некоторых частных случаях может быть уместно использование псевдокласса :target для этой
              Имхо, «:target» — не Айс — чекит забавней — если потыкать по аккордиону (по ссылке), а потом попробовать вернуться на исходную страницу, стартовую страницу, — число страниц растёт согласно кол-ву кликов.
              • НЛО прилетело и опубликовало эту надпись здесь
                • 0
                  Тут возможно в использовании таргет, есть плюс, — запоминании позиции меню, при переходе на новую страницу, вместо типового кукис запоминания. Для спойлеров конечно не айс.
                  > а вот input-ы c label-ами для каждого спойлера

                  label(ей), — нет(ниже есть пояснения, почему)
  • –1
    Aingis, не буду спорить, кому то зимой захотелось свежих огурцов, но зимой это не кошерно, нарушает установленный распорядок. Вот просто под Новый год, когда все заботы висят, захотелось отойти от обыденного…
    • 0
      Aingis: появляется лишняя точка фокуса
      А это плохо? — Вероятно кто-то найдёт это нужным
      Собственно спойлер проходит обкатку в постах на форумах.
      • 0
        Есть например у вас на форуме поле ввода комментария. Вы хотите туда быстро переместиться табом. Жмёте таб, а фокус спотыкается на куче таких спойлеров, причём пользователю даже не видны переключатели — они скрыты.
        • 0
          tabindex="-1"
          — что бы не споткнутся
          • +4
            Я знаю, потому и написал: «…хоть бы tabindex="-1" приписали…»
            • 0
              Простите, комменты читаю по диагонали — пропустил. Буду по внимательнее.
            • 0
              Я знаю, потому и написал: «…хоть бы tabindex="-1" приписали…»

              Да я не против — но расчитываю, для тех кому нужно — сами поправят ( Сейчас внесу в комменты)
              На форумах, где спойлер тестировался, достаточно удобно табом передвигаться по спойлерам, кроме нижней формы и главного меню, там элементов с фокусом нет, фокусировка на форме ввода — автомат по клику на «цитату»
  • +3
    Не далее, как сегодня вечером, пытался сделать спойлеры без JS. Не получилось. И тут ваша статья… Спасибо :)
  • +4
    Не работает в ФФ 18.0.1, Kubuntu 12.04, margin задан нормально, но он не «накрывает» текст «Показать».
    • +1
      Аналогично. Курсор даже не меняет свой вид (на указательный палец).
      • 0
        Но если вернуть checkbox через Firebug, то клик на него скрывает/раскрывает спойлер.
    • 0
      Под ArchLinux x86_64 тоже не работает. Вероятно, под другими дистрибутивами Linux в FF 18.0.1 тоже не будет работать.
  • +1
    frol, Kubuntu 12.04 — нет к сожалению, но в ХP и Win7-8 работает

    image
    • +2
      Та же ситуация.
      Ubuntu, Firefox 18.
      Чекбокс куда-то уехал: Part of a screenshot in Ubuntu FF18
  • –4
    Хм, интересно как бы реагировали на самолёт Райтов начале 20 века? Подобного рабочего варианта чисто на сss в инете не найдено, Надо отметить, что мучительные искания работоспособной версии кода вызвало изъятие <label> из использования в спойлере перед чекитом, посколь тег <label> приводил к необходимости прописывания в каждом экземпляре input в спойлере нового ID, что создавало лишние «движения» серверу.
    • 0
      Label не всегда нужно связывать по id. Достаточно поместить input и любые другие теги внутрь label. Тогда по клику по любым другим тегам, будет искомое действие. И все без id/name.
      • 0
        Carduelis,
        C оберткой в label нельзя выстроить конструкцию css скрытия, (*если только не обернуть весь спойлер, тогда кликнуть, к примеру по ссылке в его контенте нельзя без скрытия… Тут на затее не одна голова была сломана
  • 0
    На android не заработало демо, ни в родном браузере ни в fx beta… Android 4.1
  • 0
    Вот интересный пример через этот же псевдокласс — proto.io/freebies/onoff/

    p.s ксатит, кто-нибудь подскажет что вообще означают подобные конструкции?

    .spoiler >  input + .box > blockquote{
        display: none;
    }
    


    Что значит + а что >
    • 0
      Соседние и дочерние селекторы:
      htmlbook.ru/samcss/sosednie-selektory
      htmlbook.ru/samcss/dochernie-selektory
    • 0
      Piterski:, Вот интересный пример через этот же псевдокласс
      Это прошлогодний наш вариант, неудобства были описаны:
      посколь тег label приводил к необходимости прописывания в каждом экземпляре input в спойлере нового ID, что создавало лишние «движения» серверу.
  • +1
    В ИЕ9 (вин7) область для клика смещена вверх относительно текста.
    • 0
      Если можно — ccылку на скриншот? /для ИЕ обычно достаточно условного коммента/
  • –2
    Палец вверх, кто кликал на Показать! :)
  • 0
    В примере минус с плюсом нужно поменять местами. Развернутый — минус, свернутый — плюс
    • 0
      Поменял, (вчера досили сервис с первичной картинкой — пришлось срочно перезаливать — перевставлять)
  • +1
    [sarcasm] Предлагаю автору написать статью о том как можно сверстать таблицу не испульзуя table [/sarcasm]
    • 0
      Записал в ежедневник //Куда деваться, если не все публикуют идеи Посмотрел
  • 0
    А если так (для мелких кусков текста):

    .content {
    background-color:white;
    }
    
    .content  .spoiler{
    color:white;
    background-color:silver;
    }
    
    .content  .spoiler:hover{
    color:black;
    }
    
    
  • 0
    jab, Да код, в принципе, — конструктор. Можно баловаться — править дизайн в своё удовольствие, минималистически необходимые строки для работы кода даны в начале топика, — большой код, это уже личные предрасположения.
  • +1
    В ИЕ8 — наличествует пунктирная обводка чекит-бокса при фокусе;

    комменты не читал, слишком много их, может уже кто-то и предложил решение этой проблемы, навесить на бокс при фокусе CSS-свойство:

    outline:none;

    htmlbook.ru/css/outline
  • 0
    fcunited, Cпс!

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