Долой отступы между строчными элементами (и блоками)
Строчные блоки (inline-block) во многих случаях очень удобное средство разметки. Примеры их использования можно посмотреть в статьях Inline-block: простое свойство для непростых задач, Выравнивание навигации из блоков по центру, Центрирование резинового блока по горизонтали.
Вместе с тем, с ними связан подводный камень. Я бы даже сказал целый булыжник. Хочешь его увидеть? Поставь несколько строчных элементов (или строчных блоков) в ряд.
Допустим имеем такой HTML:
<ul> <li>Стороки.</li> <li>Просто</li> <li>строки</li> </ul>
Делаем элементы строчными:
li{ display:inline; }
…или строчными блоками:
li{ display:inline-block; /* Следующие две строки для IE6-7 - эмулируем поведение строчного блока*/ //display:inline; zoom:1; }
Проблема
Большинство браузеров разделяет строчные блоки (элементы) отступами. Для удобства восприятия я немного раскрасил блоки.
Давай договоримся, что здесь и далее я буду писать просто «строчный блок», а подразумевать «строчный блок (display:inline-block) или просто строчный элемент (display:inline)», поскольку проблема у них совершенно общая и лечится она тоже одинаково.
Кого лечим?
Итак строчные блоки обзавелись загадочными отступами. Конечно, это касается не только списков. Так же поведет себя и группа расположенных подряд, например, span'ов.
Справедливости ради, следует заметить, что IE6 и IE7 отрисуют все это дело без отступов:
Не будем вдаваться в детали вопроса, кто прав, а кто виноват (читай — криво поддерживает стандарты), просто добьемся кроссбраузерности. Очень удобно, когда поведение предсказуемое — не задавал я никаких отступов, значит и рисовать мне их не нужно!
На самом деле все просто — чтобы убрать отступы, нужно понять, откуда они там вообще взялись!
Откуда отступы-то?
А понять не сложно. Достаточно просто записать теги в одну строку:
<ul> <li>Стороки.</li><li>Просто</li><li>строки</li> </ul>
Чудеса! Отступы пропали сами собой! Вывод: порождают их невидимые символы между тегами — перенос или пробел.
Само собой, «писать все в одну строку» хоть и является кроссбраузерным решением проблемы, но тут не рассматривается, по понятным причинам (ну кто ж пишет без отступов?). Ищем другие пути.
Долой отступы!
Раз отступы создают символы из контейнера, здравой мыслью будет эти символы «обезвредить» — задать им font-size:0; (главное, не забыть, что это свойство наследуется и перебить его для самих потомков):
ul{ font-size:0; } li{ font-size:14px; display:inline; }
Отличное решение! Строчные блоки действительно прижались друг к другу. Осталась еще небольшая косметическая проблема: в некоторых браузерах (например, в Opera 9.5 и младше) замечен отступ сверху или снизу в пределах родителя (родитель на рисунке залит бледным серо-зеленым):
Проблема эта сродни описанной в статье IMG внутри блока — убираем странный отступ, и лечится примерно так же: добавляем line-height:0; (опять не забываем перекрыть у потомка). Итак, получаем:
ul{ font-size:0; line-height:0; } li{ font-size:14px; line-height:normal; /* ну или другое подходящее значение */ display:inline; }
Теперь-то все хорошо и красиво? Не тут-то было!
Пришла беда, откуда не ждали
Видать, действительно эти отступы должны быть! В подтверждение этому есть два железных аргумента:
- их не рисует IE6-7;
- их, несмотря на наши старания, все равно рисуют Webkit-браузеры.
Да-да! И Safari и Chrome после всех вышеизложенных ухищрений соизволили просто уменьшить отступы с трех пикселей до одного!
Update by Nick. Еще один скрытый сюрприз преподнес FF. Если масштабировать страницу иногда наблюдается дополнительный отступ в 1px сверху. Лечится это добавлением правила display: -moz-inline-stack;
Окончательное решение
Побороть webkit'ы получилось с помощью letter-spacing:-1px. При этом никаких вредных побочных эффектов обнаружено не было (если, конечно не забыть перекрыть свойство у потомков).
Окончательный CSS с кроссбраузерным решением для строчных элементов:
ul{ font-size:0; /* убираем горизонтальные отступы */ line-height:0; /* ...и вертикальные в некоторых браузерах */ letter-spacing:-1px; /* переубеждаем webkit'ы */ } li{ font-size:14px; /* Не забываем восстановить нормальные значения */ line-height:normal; letter-spacing:normal; display:inline; }
Для строчных блоков:
ul{ font-size:0; /* убираем горизонтальные отступы */ line-height:0; /* ...и вертикальные в некоторых браузерах */ letter-spacing:-1px; /* переубеждаем webkit'ы */ } li{ font-size:14px; /* Не забываем восстановить нормальные значения */ line-height:normal; letter-spacing:normal; display: -moz-inline-stack!important; display:inline-block; //display:inline; zoom:1; }
Не забудь, что свойство zoom невалидно. Поэтому в боевых условиях выноси его и хак для IE в отдельный CSS, подключаемый с помощью условных комментариев.
Проверено в:
- IE 6-8
- Firefox 3.5
- Opera 9.5-10.5
- Safari 4
- Chrome 7