Javascript перемещение dom элементов
Вроде бы можно только удалить и создать по новой DOM-элемент.
А вообще, ты бы хоть написал, что за технологии используешь.
Deleted
( 22.08.17 12:20:22 MSK )
Ответ на: комментарий от Deleted 22.08.17 12:20:22 MSK
Не поняла про какую технологию имеете в виду? Браузер? 🙂
jessgt ★
( 22.08.17 12:31:52 MSK ) автор топика
Ответ на: комментарий от Deleted 22.08.17 12:20:22 MSK
можно только удалить и создать по новой DOM-элемент
ты бы хоть написал, что за технологии используешь
Как поменять местами блоки в css
За последний год через мои руки прошли два десятка лендингов на Тильде. Некоторые я собирал сам, в некоторых помогал со сложными местами, за некоторыми просто наблюдал. Первые страницы выглядели скучно, я использовал стандартные блоки и боялся экспериментировать. Со временем я разобрался с тонкостями дизайна и с тем, как устроен код Тильды и как можно влиять на него.
Этот разбор поможет тем, кто работает с Тильдой, но использует только стандартные инструменты и либо боится, либо не знает, как расширять конструктор с помощью своих стилей и скриптов. Оказывается, не нужно быть разработчиком или изучать языки программирования, чтобы делать важные мелочи лучше.
Код в примерах может быть неидеальный, а объяснения — содержать технические неточности. Важно, что это не очередной урок про устройство интернета, а небольшой гайд, как я выжимаю максимум из Тильды без полноценного знания вёрстки или языков программирования.
Зачем это нужно?
С помощью этих простых решений я могу делать элементы, которые не соберёшь на стандартных блоках. Например, вот эта кнопка, наведите на неё мышкой (или пальцем).
Прямо на меня!
Кнопка увеличивается. Так не получится сделать с помощью простых настроек блока — можно поменять цвет или тень, но не размер при наведении. Чтобы добавить этот эффект, напишем несколько строчек кода:
.t142__submit < transition: all 400ms ease; >.t142__submit:hover
Что это значит:
Для всего с классом .t142__submit < Все анимации переходов состояния должны быть плавными и длиться 400 милисекунд >Для всего с классом .t142__submit при наведении
Тильда — гибкий инструмент и позволяет реализовать почти любую задумку. Почти — потому что иногда натыкаешься на ограничения: блокам нельзя поставить произвольную ширину, у элементов управления нельзя поменять цвет, карточки ведут себя не так, как тебе нужно.
С помощью своего кода можно менять цвета и поведение элементов, добавлять интерактивность и сложную логику. А чтобы написать простой код, вообще не нужно уметь программировать — достаточно уметь пользоваться гуглом и понимать основы вёрстки.
Если HTML и CSS вас не пугают, вы знаете, зачем нужны классы и id, то нажмите на кнопку ниже, чтобы не отвлекаться на экскурс в вёрстку. Кнопка отправит вас сразу к месту, где разберём пару примеров того, что можно сделать в Тильде, не проходя ни одного курса по программированию.
Вперёд к экспериментам
Вёрстка страницы — это просто работа с объектами, которые на ней расположены: заголовки, текст, изображения. С помощью кода мы говорим им, что они должны содержать, как выглядеть и как вести себя. Обычно за это отвечают HTML, CSS и JavaScript.
HTML — базовый язык разметки. Обычно с помощью HTML просто задают объекты на странице, их расположение и наполнение. Размечают текст на заголовки и абзацы, расставляют ссылки в нужные места, определяют положение картинок и других объектов относительно друг друга. Например, создадим какой-нибудь текст в абзаце. Абзац в HTML — это p, paragraph
Какой-то текст
С помощью стилей можно менять отступы, размер, цвет, тень, размытие объектов. Иногда для удобства стили выносят в отдельный CSS файл. При этом можно оставлять их прямо внутри HTML — это нормальный способ, мы так и будем делать в примерах. Например, добавим для абзаца стиль «цвет текста — красный»:
p
JavaScript помогает делать страницу интерактивной: добавлять анимацию и эффекты, задавать правила поведения для кнопок. В примерах ниже JS мы рассматривать не будем, но принцип такой же — находим подходящее решение и используем в своих целях.
С помощью стилей можно менять отступы, размер, цвет, тень, размытие объектов. Иногда для удобства стили выносят в отдельный CSS файл. При этом можно оставлять их прямо внутри HTML — это нормальный способ, мы так и будем делать в примерах. Например, добавим для абзаца стиль «цвет текста — красный»:
p
JavaScript помогает делать страницу интерактивной: делать анимацию и эффекты, задавать правила поведения для кнопок. В примерах ниже JS мы рассматривать не будем, но принцип такой же — находим подходящее решение и используем в своих целях.
HTML — базовый язык разметки. Обычно с помощью HTML просто задают объекты на странице, их расположение и наполнение. Текст в заголовки и абзацы, ссылки в нужные места текста, положение картинок и других объектов относительно друг друга. Например, нужно создать какой-то текст в абзаце. Абзац в HTML — это p, paragraph
Какой-то текст
Flexbox в CSS
Модель верстки известная как Flexbox (флексы), становится все популярнее. В первую очередь за счет удобного использования при создании каркасов и верстки отдельных элементов HTML страницы. Во вторую, за счет совершенно новых возможностей. В этой статье я попробую разобраться во всех тонкостях Flexbox, сделать своего рода документацию (шпаргалку) по флексам и доступно поделиться знаниями с вами. Если говорить коротко про документацию флексов, то верстка с Flexbox дает нам простые решения некогда непростых задач. Например, когда нужно выровнять элемент по вертикали, или прижать подвал к низу экрана, или просто вставить несколько блоков в один ряд, так чтобы они занимали все свободно пространство. Подобные задачи решаются и без flex. Но как правило, эти решения больше похожи на «костыли», и это еще больше усложняется когда нужно сверстать адаптивный под мобильные устройства макет. Тогда как с flexbox такие задачи решаются элегантно и именно так, как задумывает flex-модель (без добавления вспомогательных стилей и прочего). CSS Flexible Box Layout Module (CSS модуль для макетов с гибкими блоками), коротко flexbox (Флексбокс), создана, чтобы убрать недостатки при создании самых разных HTML конструкций, в том числе адаптированных под разную ширину и высоту, и сделать верстку логичной и простой. А логичный подход, как правило работает в неожиданных местах, там где результат не проверялся — логика наше все! Flexbox позволяет элегантно контролировать самые разные параметры элементов внутри контейнера: направление, порядок, ширину, высоту, выравнивание вдоль и поперек, распределение свободного места, растяжение и сжатие элементов.
Читайте также: Grid в CSS
Оглавление:
- Базовые знания
- CSS свойства Flexbox
- Для контейнера
- display:
- flex-direction:
- flex-wrap:
- flex-flow: direction wrap
- justify-content:
- align-content:
- align-items:
- column-gap:
- gap:
- Для элементов контейнера
- flex-grow:
- flex-shrink:
- flex-basis:
- flex:
- align-self:
- order:
- Заметки
- Примеры Flex верстки
- Поддержка браузерами — 99%
- Видео
- Полезные ссылки по Flex
Базовые знания
FlexBox состоит из Контейнера и его Дочерних элементов (items) (гибких элементов).
- Главная ось — главное направление движения элементов внутри контейнера. Направление главной оси можно изменить с помощью свойства flex-direction. Обратите внимание, что при смене осей, меняются только направления движения блоков внутри, а начало, конец и размер контейнера остаются прежними.
- Начало и конец главной оси — элементы располагаются от начала и до конца контейнера.
- Поперечная ось — направление движения элементов, когда они не умещаются в контейнер по направлению главной оси. Поперечная ось всегда перпендикулярна (⊥) главной.
- Начало и конец поперечной оси — по поперечной оси заполняются ряды от начала и до конца контейнера. В каждом таком ряду располагаются элементы (читайте ниже).
- Размер (главный и поперечный) — базовая величина по которой высчитывается ширина или высота внутренних элементов, если размер указан не точно (указан в процентах или не указан вообще, а элемент должен растянуться или сжаться).
Для включения flexbox, любому HTML элементу достаточно присвоить css свойство display:flex; или display:inline-flex; .
.flex12
После включения flex свойства, внутри контейнера создаются две оси: главная и поперечная (перпендикулярная (⊥), кросс ось). Все вложенные элементы (первого уровня) выстраиваются по главной оси. По умолчанию главная ось горизонтальная и имеет направление слева направо (→), а кросс ось соответственно вертикальная и направлена сверху вниз (↓).
Главную и кросс оси можно поменять местами, тогда элементы будут располагаться сверху вниз (↓) и когда перестанут вмещаться в высоту то будут двигаться слева направо (→) — то есть оси просто поменялись местами. При этом начало и конец расположения элементов не меняется — меняются только направления (оси)! Именно поэтому нужно представлять себе оси внутри контейнера. Однако не нужно думать, что есть какие-то там «физические» оси и они на что-то влияют. Ось тут — это только лишь направление движения элементов внутри контейнера. Например, если мы указали выравнивание элементов по центру основной оси и потом изменили направление этой основной оси, то изменится и выравнивание: элементы были в середине по горизонтали, а стали в середине по вертикали. См. пример.
Еще одной важной особенностью Флекс-бокс является наличие рядов в поперечном направлении. Чтобы понять о чем речь, давайте представим что есть главная горизонтальная ось, много элементов и они не «лезут» в контейнер, поэтому переходят на другой ряд. Т.е. контейнер выглядит так: контейнер, внутри него два ряда, в каждом ряду по несколько элементов. Представили? А теперь запомните, что выравнивать по вертикали мы можем не только элементы, но и ряды! Как это работает хорошо видно в примере к свойству align-content. А вот так это выглядит схематически:
CSS свойства, которые могут влиять на модель построения макета: float , clear , vertical-align , columns не работают во flex конструкции. Тут используется другая модель построения макета и эти css свойства просто игнорируются.
CSS свойства Flexbox
Flexbox содержит разные css правила для управления всей flex конструкцией. Одни нужно применять к основному контейнеру, а другие к элементам этого контейнера.
Для контейнера
Включает flex свойство для элемента. Под это свойство попадает сам элемент и вложенные в него элементы: затрагиваются только потомки первого уровня — они станут элементами flex контейнера.
- flex — элемент растягивается на всю ширину и имеет свое полное пространство среди окружающих блоков. Происходит перенос строк в начале и в конце блока.
- inline-flex — элемент обтекается другими элементами. При этом его внутренняя часть форматируется как блочный элемент, а сам элемент — как встроенный.
flex и inline-flex отличаются тем что по-разному взаимодействуют с окружающими элементами, подобно display:block и display:inline-block .
Изменяет направление главной оси контейнера. Поперечная ось меняется соответственно.
- row (default) — направление элементов слева направо (→)
- column — направление элементов сверху вниз (↓)
- row-reverse — направление элементов справа налево (←)
- column-reverse — направление элементов снизу вверх (↑)
Нужно понимать, что при переходе с row на column или с row-reverse на column-reverse меняется только направление осей и больше ничего. Начало и конец расположения блоков остается неизменным (см. картинку в начале). Т.е. если при row элементы начинали свой путь справа/сверху, то при column все останется также — изменится только направление. (см. пример свойства flex-wrap)
Управляет переносом непомещающихся в контейнер элементов.
- nowrap (default) — вложенные элементы располагаются в один ряд (при direction=row) или в одну колонку (при direction=column) независимо от того помещаются они в контейнер или нет.
- wrap — включает перенос элементов на следующий ряд, если они не помещаются в контейнер. Так включается движение элементов по поперечной оси.
- wrap-reverse — тоже что wrap только перенос будет не вниз, а вверх (в обратном направлении).
Объединяет оба свойства flex-direction и flex-wrap . Они часто используются вместе, поэтому чтобы писать меньше кода было создано свойство flex-flow .
flex-flow принимает значения двух этих свойств, разделенные пробелом. Или можно указать одно значение любого свойства.
/* только flex-direction */ flex-flow: row; flex-flow: row-reverse; flex-flow: column; flex-flow: column-reverse; /* только flex-wrap */ flex-flow: nowrap; flex-flow: wrap; flex-flow: wrap-reverse; /* сразу оба значения: flex-direction и flex-wrap */ flex-flow: row nowrap; flex-flow: column wrap; flex-flow: column-reverse wrap-reverse;
justify-content:
Выравнивает элементы по основной оси: если direction=row, то по горизонтали, а если direction=column, то по вертикали.
- flex-start (default) — элементы будут идти с начала (в конце может остаться место).
- flex-end — элементы выравниваются по концу (место останется в начале)
- center — по центру (место останется слева и права)
- space-between — крайние элементы прижимаются к краям (место между элементами распределяется равномерно)
- space-around — свободное пространство равномерно распределяется между элементами (крайние элементы не прижимаются к краям). Пространство между краем контейнера и крайними элементами будет в два раза меньше чем пространство между элементами в середине ряда.
- space-evenly — тоже что space-around , только расстояние у крайних элементов до краев контейнера такое же как и между элементами.
Выравнивает ряды, в которых находятся элементы по поперечной оси. То же что justify-content только для противоположной оси.
Заметка: Работает только когда высота контейнера фиксированная (выше чем ряды внутри него).
Т.е. если flex-direction: row , то это свойство будет выравнивать невидимые ряды по вертикали ¦ . Тут важно заметить, что высота блока должна быть задана жестко и должна быть больше высоты рядов иначе сами ряды будут растягивать контейнер и любое их выравнивание теряет смысл, потому что между ними нет свободного места. А вот когда flex-direction: column , то ряды движется по горизонтали → и ширина контейнера почти всегда больше ширины рядов и выравнивание рядов сразу приобретает смысл.
Это свойство мало где нужно и вместо него чаще используется align-items (см.ниже).
- stretch (default) — ряды растягиваются заполняя строку полностью
- flex-start — ряды группируются в верхней части контейнера (в конце может остаться место).
- flex-end — ряды группируются в нижней части контейнера (место останется в начале)
- center — ряды группируются по центру контейнера (место останется по краям)
- space-between — крайние ряды прижимаются к краям (место между рядами распределяется равномерно)
- space-around — свободное пространство равномерно распределяется между рядами (крайние элементы не прижимаются к краям). Пространство между краем контейнера и крайними элементами будет в два раза меньше чем пространство между элементами в середине ряда.
- space-evenly — тоже что space-around , только расстояние у крайних элементов до краев контейнера такое же как и между элементами.
Выравнивает элементы по поперечной оси внутри ряда (невидимой строки). Т.е. сами ряды выравниваются через align-content , а элементы внутри этих рядов (строк) через align-items и все это по поперечной оси. По главной оси такого разделения нет, там нет понятия рядов и элементы выравниваются через justify-content .
- stretch (default) — элементы растягиваются заполняя строку полностью
- flex-start — элементы прижимаются к началу ряда
- flex-end — элементы прижимаются к концу ряда
- center — элементы выравниваются по центру ряда
- baseline — элементы выравниваются по базовой линии текста
Задает размер промежутка между элементами контейнера. Соответственно:
- column-gap: — раздвигает только колонки.
- gap: — раздвигает и колонки и ряды.
Размеры можно указать в абсолютных или относительных величинах: px, em, . или в % .
Поддержка gap ( у column-gap поддержка точно такая же ):
Для элементов контейнера
Задает коэффициент увеличения элемента при наличии свободного места в контейнере. По умолчанию flex-grow: 0 т.е. никакой из элементов не должен увеличиваться и заполнять свободное место в контейнере.
По умолчанию flex-grow: 0
- Если всем элементам указать flex-grow:1 , то все они растянуться одинаково и заполнять все свободное место в контейнере.
- Если одному из элементов указать flex-grow:1 , то он заполнит все свободное место в контейнере и выравнивания через justify-content работать уже не будут: свободного места нет выравнивать нечего.
- При flex-grow:1 . Если один из них имеет flex-grow:2, то он будет в 2 раза больше, чем все остальные
- Если все flex-блоки внутри flex-контейнера имеют flex-grow:3 , то они будут одинакового размера
- При flex-grow:3 . Если один из них имеет flex-grow:12 , то он будет в 4 раза больше, чем все остальные
Как это работает? Допустим, что контейнер имеет ширину 500px и содержит два элемента, каждый из которых имеет базовую ширину 100px. Значит в контейнере остается 300 свободных пикселей. Теперь, если первому элементу укажем flex-grow:2; , а второму flex-grow: 1; , то блоки займут всю доступную ширину контейнера и ширина первого блока будет 300px, а второго 200px. Объясняется это тем, что доступные 300px свободного места в контейнере распределились между элементами в соотношении 2:1, +200px первому и +100px второму.
Заметка: в значении можно указывать дробные числа, например: 0.5 — flex-grow:0.5
flex-shrink:
Задает коэффициент уменьшения элемента. Свойство противоположное flex-grow и определяет как элемент должен сжиматься, если в контейнере не остается свободного места. Т.е. свойство начинает работать, когда сумма размеров всех элементов больше чем размер контейнера.
По умолчанию flex-shrink:1
Допустим, что контейнер имеет ширину 600px и содержит два элемента, каждый из которых имеет ширину 300px — flex-basis:300px; . Т.е. два элемента полностью заполняют контейнер. Первому элементу укажем flex-shrink: 2; , а второму flex-shrink: 1; . Теперь уменьшим ширину контейнера на 300px, т.е. элементы должны сжаться на 300px чтобы находится внутри контейнера. Сжиматься они будут в соотношении 2:1, т.е. первый блок сожмется на 200px, а второй на 100px и новые размеры элементов станут 100px и 200px.
Заметка: в значении можно указывать дробные числа, например: 0.5 — flex-shrink:0.5
Устанавливает базовую ширину элемента — ширину до того как будут высчитаны остальные условия влияющие на ширину элемента. Значение можно указать в px, em, rem, %, vw, vh и т.д. Итоговая ширина будет зависеть от базовой ширины и значений flex-grow, flex-shrink и контента внутри блока. При auto элемент получает базовую ширину относительно контента внутри него.
По умолчанию: auto
Иногда лучше установить ширину элемента жестко через привычное свойство width . Например, width: 50%; будет означать, что элемент внутри контейнера будет ровно 50%, однако при этом все также будут работать свойства flex-grow и flex-shrink . Такое может быть нужно, когда элемент растягивается контентом внутри него, больше указанного во flex-basis. Пример смотрите в заметках.
flex-basis будет «жестким», если обнулить растяжение и сжатие: flex-basis:200px; flex-grow:0; flex-shrink:0; . Все это можно записать так flex:0 0 200px; .
Короткая запись трех свойств: flex-grow flex-shrink flex-basis .
По умолчанию: flex: 0 1 auto
Однако можно указать и одно, и два значения:
flex: none; /* 0 0 auto */ /* число */ flex: 2; /* flex-grow (flex-basis переходит в 0) */ /* не число */ flex: 10em; /* flex-basis: 10em */ flex: 30px; /* flex-basis: 30px */ flex: auto; /* flex-basis: auto */ flex: content; /* flex-basis: content */ flex: 1 30px; /* flex-grow и flex-basis */ flex: 2 2; /* flex-grow и flex-shrink (flex-basis переходит в 0) */ flex: 2 2 10%; /* flex-grow и flex-shrink и flex-basis */
Позволяет изменить свойство align-items , только для отдельного элемента.
По умолчанию: от align-items контейнера
- stretch — элемент растягиваются заполняя строку полностью
- flex-start — элемент прижимаются к началу строки
- flex-end — элемент прижимаются к концу строки
- center — элемент выравниваются по центру строки
- baseline — элемент выравниваются по базовой линии текста
Позволяет менять порядок (позицию, положение) элемента в общем ряду.
По умолчанию: order: 0
По умолчанию элементы имеют order: 0 и ставятся в порядке их появления в HTML коде и направления ряда. Но если изменить значение свойства order, то элементы будут выстраиваться в порядке значений: -1 0 1 2 3 . . Например если одному из элементов указать order: 1 , то сначала будут идти все нулевые, а потом элемент с 1.
Так можно, например, первый элемент перекинуть в конец, при этом не меняя направление движения остальных элементов или HTML код.
Заметки
Чем отличается flex-basis от width?
Ниже важные различия между flex-basis и width / height:
- flex-basis работает только для главной оси. Это значит что при flex-direction:row flex-basis контролирует ширину (width), а при flex-direction:column контролирует высоту (height). Смотрите пример.
- flex-basis применяется только к flex элементам. А значит если отключить flex у контейнера это свойство не будет иметь эффекта.
- Абсолютные элементы контейнера не участвуют во flex конструкции. А значит, flex-basis не влияет на элементы flex контейнера, если они абсолютны position:absolute . Им нужно будет указать width / height.
- При использовании css свойства flex три значения: flex-grow / flex-shrink / flex-basis можно скомбинировать и записать коротко — flex:0 0 50% . Тогда как при использовании width, grow и shrink придется писать отдельно. Например: flex:0 0 50% == width:50%; flex-shrink:0; . Иногда это просто неудобно.
По возможности все же отдавайте предпочтение flex-basis. Используйте width только когда не подходит flex-basis.
Отличие flex-basis от width — баг или фича?
Контент внутри flex элемента распирает его и не может выйти за его пределы. Однако если установить ширину через width или max-width , а не flex-basis , то элемент внутри flex контейнера сумеет выйти за пределы этого контейнера (иногда нужно именно такое поведение). Пример:
Примеры Flex верстки
В примерах нигде не используются префиксы для кроссбраузерности. Сделал я так для удобного чтения css. Поэтому примеры смотрите в последних версиях Chrome или Firefox.
#1 Простой пример с выравниванием по вертикали и горизонтали
Начнем с самого простого примера — выравнивание по вертикали и горизонтали одновременно и при любой высоте блока, даже резиновой.
Текст по середине.parent < display: flex; >.child
Или так, без блока внутри:
Текст по середине.center-text
#1.2 Разделение (разрыв) между элементами флекс блока
Чтобы расположить элементы контейнера по краям и произвольно выбрать элемент после которого будет разрыв, нужно использовать свойство margin-left:auto или margin-right:auto .
#2 Адаптивное меню на flex
Сделаем меню в самом верху страницы. На широком экране оно должно быть справа. На среднем выравниваться по середине. А на маленьком каждый элемент должен быть на новой строке.
Главная О нас Продукты Контакты
Перейдите в jsfiddle.net и изменяйте ширину секции «результат»
#3 Адаптивные 3 колонки
Этот пример показывает как быстро и удобно сделать 3 колонки, которые при сужении будут превращаться в 2 и затем в 1.
Обратите внимание, что сделать это можно без использования media правил, все на flex.
123456
Перейдите в jsfiddle.net и изменяйте ширину секции «результат»
#4 Адаптивные блоки на flex
Допустим нам нужно вывести 3 блока, один большой и два маленьких. При этом нужно чтобы блоки подстраивались под маленькие экраны. Делаем:
123
Перейдите в jsfiddle.net и изменяйте ширину секции «результат»
#5 Галерея на flex и transition
Этот пример показывает как быстро можно сделать симпатичный аккордеон с картинками на flex. Обратите внимание на свойство transition для flex.
#6 Флекс во флекс (просто пример)
Задача сделать гибкий блок. Так чтобы начало текста в каждом блоке находилось на одной линии по горизонтали. Т.е. при сужении ширины, блоки растут в высоту. Нужно, чтобы картинка была вверху, кнопка всегда внизу, а текст по середине начинался по одной горизонтальной линии.
Для решения этой задачи, сами блоки растягиваются флексом и им установлена максимально возможная ширина. Каждый внутренний блок также является флекс конструкцией, с повернутой осью flex-direction:column; и элемент в середине (где находится текст) растягивается flex-grow:1; чтобы заполнить всё свободное пространство, так достигается результат — текст начинался с одной линии.
Еще примеры
Поддержка браузерами — 99%
Полной поддержки разумеется нет, однако все современные браузеры поддерживают flexbox конструкции. Для некоторых все еще нужно указывать префиксы.
Чтобы знать какие префиксы актуальны на сегодня (июнь. 2019), приведу пример всех flex правил с нужными префиксами:
/* Контейнер */ .flex < display:-ms-flexbox; display:flex; display:-ms-inline-flexbox; display:inline-flex; -ms-flex-direction:column; flex-direction:column; -ms-flex-wrap:wrap; flex-wrap:wrap; -ms-flex-flow:column wrap; flex-flow:column wrap; -ms-flex-pack:justify; justify-content:space-between; -ms-flex-line-pack:distribute; align-content:space-around; >/* Элементы */ .flex-item
Лучше если свойства с префиксами будут идти до оригинального свойства.
В этом списке нет ненужных на сегодня (по caniuse) префиксов, но вообще префиксов больше.
Видео
Ну и не забывайте про видео, там порой тоже интересно и понятно. Вот парочка популярных:
Полезные ссылки по Flex
- flexboxfroggy.com — игра обучающая flexbox.
- Flexplorer — наглядный конструктор flex кода.
- Шпаргалка Flexbox
Использовал при написании:
- https://habrahabr.ru/post/242545/
- http://html5.by/blog/flexbox/
- https://css-tricks.com/snippets/css/a-guide-to-flexbox/
- https://www.w3.org/TR/css-flexbox-1/
Очень опрятный сайт с рецептами различных блюд homyachishka.ru. На сайте Хомячишка.ru можно найти очень простые, но в тоже время вкусные рецепты.
До этого из: CSS
Раскладка в CSS: float
Как и позиционирование, float используется для того, чтобы двигать боксы. Но в отличие от позиционирования, которым можно двигать боксы практически произвольно, все, что может float — это сдвинуть элемент к одной из сторон потока, правой или левой.
При этом сам бокс и следующие за ним в потоке приобретают интересное поведение:
- Float’нутый бокс смещается по горизонтали и прилипает к одной из сторон родителя.
- Float’нутый бокс перестает раздаваться на всю ширину родительского бокса-контейнера (как это происходит с блоками в потоке). С его неприжатой к родителю свободной стороны появляется свободное место.
- Следующие за ним блочные боксы подтягиваются вверх и занимают его место, как если бы float’нутого бокса в потоке не было.
- Строчные же боксы внутри подвинувшихся наверх блоков начинают обтекать float’нутый бокс со свободной стороны.
Хочу еще раз подчеркнуть неочевидную сразу вещь: сама коробка блока, следующего за float’ом, подлезает под него и занимают всю ширину потока, а вот текст внутри этого блока смещается в сторону и обтекает float.
Дальше интересно, как себя ведут float’нутые в одну сторону боксы, которые идут один за другим. В этом случае следующий бокс будет пытаться уместиться сбоку от предыдущего, с его свободной стороны. И только если ему там не будет достаточно места, тогда он сместится ниже и будет пытаться уместиться уже там.
Есть еще один маленький технический аспект, не обязательный для понимания всей «механики». Заfloat’ить можно как блочные боксы, так и строчные. При этом строчные тут же автоматически становятся блочными. То есть, писать display:block; для float’а излишне.
Из двух описанных особенностей float’ов — прижимание к краю и стыкование сбоку друг друга — вытекают два основных применения их в раскладке:
- разделение страницы на колонки
- горизонтально расположенные меню
Колонки
Колонки — это когда блоки текста расположены рядом друг с другом и имеют одинаковую высоту.
Все колоночные раскладки я буду рассматривать на вот таком простейшем HTML’ном коде с двумя блоками:
body> div id="sidebar"> . div> div id="content"> . div> body>
Сразу стоит сказать, что делать колонки в растягивающемся по ширине контейнере сложнее, чем с заданной шириной. Тут есть два принципиально разных подхода, подходящих для разных случаев.
Пропорциональная ширина
Если нужно, чтобы ширина колонок менялась пропорционально, при изменении ширины страницы, то подход такой:
#content < float:right; width:70%; > #sidebar < float:left; width:30%; >
То есть два блока float’ятся рядом в разные стороны, а их ширина делится в нужном процентном соотношении. Этот способ позволяет легко поменять колонки местами — просто поменяв значения right и left .
Растягивание только одной колонки
Если нужно, чтобы менялась только ширина основной колонки, то предыдущий способ не подходит. Дело в том, что в CSS, к сожалению, нельзя напрямую сформулировать такую вещь как «вся доступная ширина минус конкретное число».
Если блоку в прямом потоке задать, скажем, левый margin , то его ширина соответственно ужмется. А это именно то поведение, которого мы хотели добиться от одной из колонок.
Итак, для нужного нам эффекта мы дадим основному блоку левый margin, чтобы он ужался направо, а боковую панель заfloat’им на это место:
#sidebar < float:left; width:200px; > #content < margin-left:200px; >
Но у второго способа есть один очень серьезный недостаток. Обратите внимание, что в исходном HTML блок «sidebar» идет до блока «content» с основным содержимым. Не нужно думать, что так сделано случайно. Так сделано специально, потому что иначе этот самый второй способ с наложением колонки поверх margin’а не работал бы.
Как я написал в начале статьи, float’ы сдвигаются только в сторону и дают место следующим блоками, которые съезжают наверх. Поэтому принципиально, чтобы «sidebar» был уже наверху, и тогда основной блок подъедет к нему. Если «sidebar» идет после основного блока, то он так и останется ниже, и ни на какие колонки это похоже не будет.
Это действительно плохо, потому что перечеркивает одну из основных идей CSS: отделение оформления от содержания. Получается, что мы захотели изменить только дизайн, а если блоки расположены «не так», то придется лезть еще и в HTML-шаблоны. Кроме того, с точки зрения структуры могут быть свои веские основания располагать блоки так, а не иначе. Например чтобы пользователь мог начать читать основной текст страницы, не дожидаясь загрузки навигации.
Фиксированная ширина
Все резко упрощается, когда колонки помещаются в фиксированную ширину контейнера. В этом случае лучше всего использовать первый способ (float’ить все колонки), и ширину уже можно задавать не только в процентах, но и в чем хотите, поскольку ее можно точно вычислить.
Высота колонок
Опять-таки, я далеко не случайно «отрезал» на картинках нижнюю часть блоков :-). Иначе бы они как колонки совсем не выглядели, потому что, как нетрудно убедиться, если применить те фрагменты CSS, что я привел, и раскрасить колонки разными цветами, то их высота оказывается разной. Она зависит от количества содержимого в этих блоках.
Этот некрасивый эффект можно обойти несколькими способами.
Первый способ называется «Ложные колонки» («Faux columns»).
Вместо того, чтобы назначать фон самим колонкам, они оставляются прозрачными, а вот их контейнеру назначается фоновая картинка шириной во весь контейнер и повторяющаяся по вертикали. Части этой картинки, находящиеся под разными колонками, красятся в разные цвета и при повторении вниз это дает нужный визуальный эффект.
Что в ложных колонках замечательно — так это то, что вы можете не ограничивать себя на фоновой картинке ровными цветами. На ней, например можно нарисовать эффект тени между колонками, повторяющиеся горизонтальные полоски в виде фона, орнамент по краям.
Для случая, когда одна из колонок фиксирована по ширине, фон приспособить можно.
Суть состоит в том, чтобы поместить фоновую картинку только под ту колонку, ширина которой известна. Остальное место будет занято фоновым цветом контейнера, а не картинкой.
Возьмем наш пример и сделаем колонку «sidebar» справа шириной 200 пикселов, а «content» пусть растягивается. Для «sidebar» подготовим картинку размерами 200х1 например ровного синего оттенка. А под «content» отведем желтоватый.
В стилях это выглядит так:
#sidebar < float:right; width:200px; > #content < margin-right:200px; > body < background:url(bg.png) #FFD right top repeat-y; >
Единственное правило для контейнера (body) задает все поведение фона:
- указывается URL картинки ( bg.png )
- цвет фона в тех местах, где ее не будет ( #FFD )
- положение картинки прижатой к правому краю ( right top )
- повторение картинки вниз ( repeat-y )
В реальном примере в CSS еще была пара правил для цвета букв и борьбы с границами, которые сейчас не существенны.
Другой способ уравнивания колонок по высоте был описан недавно и уже сильно известен, поскольку удобен.
Идея его состоит в том, чтобы неравенство высот колонок спрятать, неимоверно удлинив их вниз, чтобы их концы были за пределами реального содержимого страницы. Добиваются этого тем, что сначала ставят колонкам очень большой отступ ( padding ) вниз, который закрашивается цветом фона. А чтобы все остальное содержимое тоже не сдвигалось туда далеко, колонкам назначается отрицательная граница ( margin ) такого же размера:
#content, #sidebar < padding-bottom:32767px; margin-bottom:-32767px; >
Странное число обусловлено тем, что это максимум, который может позволить браузер Safari. На самом деле оно не настолько странное. Кому интересно, это максимальное знаковое целое число, если представлять его 16 битами.
В итоге все, что идет за колонками смещается и находится прямо под содержимым самой длинной из них, а колонки удлиняются вниз. Некрасиво одно — из-за длинных колонок сама страница становится такой же длинной. Чтобы с этим бороться, надо их контейнеру проставить свойство overflow:hidden , которое заставляет контейнер просто отрезать и не показывать то, что выходит за его пределы.
У моего примера, который я взял в самом начале, есть, правда, одна загвоздка. Там колонки лежат прямо в body . А если body проставить overflow:hidden , то браузеры отменяют скроллинг у страницы начисто. Даже если реальное содержимое выше окна. Поэтому колонки надо завернуть в еще один элемент, например div . Но справедливости ради надо сказать, что на практике колонки и так бывают во что-нибудь уже завернуты.
Засада
Поскольку float’ы не придумывались как средство создания колонок, это обязательно вылезет чем-нибудь уродливым и аукнется увеличением расхода анальгина (некоторые предпочитают темпалгин или парацетамол).
Причем «вылезет» — в прямом смысле. Давайте немного подвинем наш «голый» пример в сторону реальности, добавив над колонками шапку и внизу какой-нибудь тоже блок с текстом.
body> div id="header">. div> div id="main"> div id="content"> . div> div id="sidebar"> . div> div> div id="footer">. div> body>
Для простоты выберем нехитрый колоночный дизайн с фиксированной шириной. Шапку и нижний блок сделаем синими с белыми буквами, основное содержимое белым, а дополнительную колонку тоже синей, но чуть светлее. Цвета колонкам зададим способом «Faux columns».
/* Раскладка в колонки */ body < width:600px; margin:0 auto; > #content < float:left; width:450px; > #sidebar < float:right; width:150px; > /* Цвета */ #main < background:url(bg.png) right top repeat-y; > #header, #footer < background:#238; color:white; >
Всякие отступы и шрифты я снова опустил для простоты восприятия. Добавим тестового текста и запускаем:
Хм. Ну, колонки, в общем, даже можно разглядеть! Не придерешься! Однако как ни крути, но выглядит все не так, как задумано, а даже можно сказать, все превратилось в некую кашу из цветов и букв.
Чтобы понять, почему так происходит, надо вспомнить описание того, как работает float. А именно, что блоки, идущие за float’ами перестают эти float’ы замечать и подтягиваются вверх. Более того, сам контейнер, в котором float’ы находятся, тоже перестает их замечать и float’нутые блоки проваливаются через низ контейнера, если он заканичвается раньше.
Теперь посмотрим на наш код. Оба float’нутых блока «content» и «sidebar» находятся внутри блока «main». И больше ничего в «main» нет. А раз ему нечего больше содержать, то его высота схлопывается в нуль! Поэтому и не видно на картинке ни белого фона «content», ни светло-синего фона «sidebar», потому что эти цвета назначены в виде фона «main».
Дальше — «footer». Он, подчиняясь все тому же правилу, тоже не видит float’нутых блоков и подтягивается наверх прямо к самому заголовку (поскольку «main» — нулевой высоты). Но в «footer» есть текст. Текст этот уже должен обтекать float’ы: справа «content» и слева «sidebar». Между колонками места не осталось, поэтому текст может начаться только под одной из колонок, которая первая кончится. Там он и есть. Таким образом, «footer», подтянувшись под заголовок, продолжается вниз, пока не закончится весь его текст. И весь этот синий фон, что ниже заголовка — это «footer» и есть.
Зачем такая сложность
Описанное поведение должно внушать недоуменние. Зачем надо было придумывать такие сложности: разделить понятие блока так, чтобы цвета и рамки наверх, а текст — на месте? Но смысл, конечно, есть. Это, наряду со схлопыванием границ, попытка заставить боксовую модель CSS нормально вести себя в условиях простого потока текста. Подробное классическое объяснение этому феномену есть все у того же Эрика Мейера в статье «Containing Floats». Постараюсь кратко передать суть.
Представьте себе обычный поток абзацев — блоков с текстом — без всякого позиционирования. В одном из абзацев встречается картинка, которую хочется сдвинуть, скажем, влево, чтобы текст ее обтекал. Такое раньше в HTML достигалось свойством align="left" , но в духе вынесения оформления из HTML в стили, для этой функции как раз и придумали свойство float . То есть вместо align этой картинке приписывается float:left .
Пусть сдвигаемая картинка занимает по высоте больше, чем текст абзаца. Если она будет растягивать свой абзац и отодвигать начало следующего ниже, то это будет выглядеть некрасиво из-за увеличенного расстояния между строками соседних абзацев. Поэтому она и проваливается через все границы блоков, сохраняя между ними красивые отступы, а текст ее обтекает.
Решения
Итак, поведение с проваливанием понятно, но оно удобно для непозиционированного текста, а для раскладки — совсем неудобно. Существует два подхода устранящих оба проявления этого свойства: подтягивание следующих боксов наверх и проваливание через низ контейнера.
Для устранения подтягивания блоков существует специальное свойство — clear . Оно заставляет элемент сдвигаться вниз, пока сбоку от него не останется float’ов. Причем можно управлять, с какого именно бока не должно быть float’ов:
- clear:left
- следит, чтобы float’ов не было слева
- следит, чтобы float’ов не было справа
- следит, чтобы float’ов не было с обеих сторон
Таким образом, если мы скажем нашему «footer»у:
#footer < clear:both; >
. чтобы слева и справа от него не было float’нутых колонок, то он сдвинется вниз как раз туда, где они обе кончаются.
Но это не решает другой проблемы: того, что float’ы проваливаются через «main», и тот схлопывается, в результате чего не видно колоночного фона, который ему назначен. Проваливание можно победить двумя способами.
Можно явно спозиционировать контейнер каким-нибудь образом. Насколько я понимаю логику спецификации, поведение проваливания считается логичным только в простом потоке. В других случаях оно только мешает. И так оно и есть, как мы убедились. То есть достаточно назначить контейнеру например position:absolute или float:left и ничего не будет проваливается, контейнер будет полностью заключать в себя и текст, и float’ы. В нашем случае (и в большинстве случаев, кстати) это решение вполне подойдет.
Другой интересный способ связан с побочным эффектом свойства overflow. Само по себе оно предназначено для того, чтобы определять, как будет вести себя контейнер при переполнении, когда не может вместить свое содержимое. У него есть четыре значения:
- visible
- содержимое переходит через край и его нормально видно (это поведение по умолчанию)
- содержимое отсекается за границами контейнера и его там никак не видно
- если содержимое переполняет контейнер, у него появляется скроллбар, позволяющий проматывать содержимое, если нет — не появляется
- похоже на auto , только скроллбар у контейнера есть всегда, даже когда содержимое его не переполняет
Так вот побочный эффект заключается в том, что если контейнеру поставить любой overflow , кроме обычного visible , он вдруг растягивается и заключает в себя float’ы, которые в нем сидят, устраняя проваливание.
Какой же overflow использовать? Сразу отпадает scroll — всегда висящие скроллбары явно не нужны. Остаются auto и hidden, которые отличаются только тем, появляется скроллбар при переполнении или нет. Но у нас никакого переполнения нет, наоборот, этим свойством мы заставили контейнер дополнительно растянуться, чтобы он охватывал все свои элементы. Поэтому использовать можно любое значение.
Я суеверно стараюсь использовать hidden , чтобы не появлялось скроллбаров, если из-за каких-то глюков переполнение вдруг возникнет.
У решения с overflow есть одна загвоздка, связанная с поведением Некоторого Браузера™. Оно работает только если контейнеру явно назначены ширина или высота. Из-за этого им иногда неудобно пользоваться, когда вам нужны автоматические размеры, а не жесткие.
Итак, в итоге, чтобы исправить наш пример с колонками, надо сделать так:
#main < width:100%; overflow:hidden; >
Кстати! Если бы для рисования фона под колонками я использовал не faux columns, а способ с длинным padding’ом, то он бы потребовал использовать overflow:hidden для «main», что заодно решает и проблему с проваливанием.
Меню
Напомню, что если несколько идущих подряд блоков заfloat’ить в одну сторону, то каждый следующий будет пытаться разложиться со свободной стороны от предыдущего. Этот эффект широко используется для того, чтобы превращать списки разделов сайта в горизонтально расположенные меню.
Возьмем такой список:
ul> li>a href="/">Начало a> li> li>a href="catalog/">Каталог a> li> li>a href="basket/">Корзина a> li> li>a href="help/">Справка a> li> ul>
Чтобы это было похоже на меню, надо заfloat’ить все li влево, убрать у них атрибутику списка (отступы и буллиты) и еще добавить для красоты отступы, фон и рамку:
/* раскладка */ ul, li < float:left; list-style:none; margin:0; padding:0; > /* вид */ li < padding:2px 10px; font:Bold Small Tahoma; background:#35C; color:white; border:solid 1px; border-color:#46F #238 #238 #46F; > a < color:white; text-decoration:none; >
Обратите внимание, что для раскладки все свойства назначаются и для элементов ul , и для li . Это удобно свести в одно правило, потому что:
- float:left нужен элементам списка, чтобы они разложились горизонтально, а самому списку — чтобы элементы через него не проваливались;
- нулевые margin и padding устраняют отступы, которые браузеры делают для списков по умолчанию, но они это делают очень по-разному, поэтому проще сказать «всем всё по нулям», чем помнить что отдельно для какого элемента проставлять.
Мораль
Механизм float — еще одно средство раскладки наряду с абсолютным позиционированием.
Он отличаются в лучшую сторону, позволяя оставить элемент в потоке, что очень удобно для колоночной раскладки.
Однако его минусами является меньшая гибкость из-за того, что элементы нельзя двигать произвольно, и потому что возможность его применять может зависеть от порядка элементов в HTML-разметке.