Помните, я сказал вам, что отделение макета от стиля — это хорошо? Ну забудь об этом!
Важным является не разделение макета и стиля, а скорее
- Создайте уровень абстракции поверх HTML и CSS
- Все четко и в одном месте
Уровень абстракции поверх HTML
Elm имеет общий HTML API, который позволяет нам писать все, что вы хотите.
Например
node “foo” [ attribute “bar” “x”] [ text “ciao” ]
генерировать
<foo bar=”x”>ciao</foo>
Это дает нам возможность написать что-то неправильное, например
img [] [ img [ src “https://loremflickr.com/320/240/cat" ] [] ]
Это неправильно, потому что ‹img› — это пустой элемент, у которого не может быть дочерних элементов.
Вместо этого в элементах стиля изображения определяются как
image : List (Attribute msg) -> { src : String, description : String } -> Element msg
Эта подпись типа учит нас тому, что image
принимает только список атрибутов (таких как ширина, длина и т. д.) и два параметра: src
и description
.
Таким образом, дети не допускаются, и это также вынуждает нас дать ему описание, делающее наше приложение более доступным.
Все хорошие вещи!
Другим примером является el
(аналог <div>
в области HTML), определяемый как
el : List (Attribute msg) -> Element msg -> Element msg
Подобно image
и в отличие от <div>
, он допускает только один дочерний элемент вместо списка дочерних элементов. Это потому, что style-elements
хочет узнать больше о нашем макете, поэтому он предоставляет специальные конструкторы для каждого случая:
- Несколько элементов подряд → используйте
Element.row
- Несколько элементов в столбцах → используйте
Element.column
- Куча текста → используйте
Element.paragraph
- Несколько групп текста в столбце → используйте
Element.column
илиElement.textColumn
За кулисами для нас делается много работы, поэтому простой
el [] <| text “ciao”
сгенерировать этот HTML
<div class=”se el width-content height-content self-center-x content-center-x content-center-y”> ciao </div>
плюс куча элементов CSS, заключенных в теги <style>
. Сложный? Что ж, хорошая новость заключается в том, что нам не нужно заботиться обо всем этом, но иногда может быть интересно взглянуть, как это работает.
Некоторые элементы HTML не имеют аналога в style-elements
, поэтому требуется немного опыта.
Некоторые примеры:
<div>
→el
,row
,column
,textColumn
<p>
→paragraph
<table>
→table
<img>
→image
<a>
→link
<h1>
→el [ Area.heading 1 ]
<input type=”text”>
→Input.text
Уровень абстракции поверх CSS
- Без обмана CSS
- Без маржи
- Нет CSS Grid, да CSS Flexbox (под капотом)
Без обмана CSS
Начнем с полного простого примера:
(кстати, layout
это корень нашего макета и он по сути трансформирует Element.Element
в Html.Html
так что Elm может все обработать)
module Main exposing (main) import Element exposing (..) main = layout [] <| el [] <| text "ciao"
Это помещает наш текст в середину экрана, выровненный как по горизонтали, так и по вертикали.
У нас также есть такие атрибуты, как centerY
, так что вы помните все приемы из прекрасной книги Центрирование в CSS: полное руководство? Теперь мы можем, наконец, удалить его из нашей закладки.
И, надеюсь, забыть обо всех приемах CSS, которым мы научились за эти годы.
Есть много атрибутов, которые совпадают с CSS 1:1, поэтому преобразование из CSS не должно быть слишком сложным.
Например:
border-color
→Border.color
background-color
→Background.color
Остальные немного отличаются
color
→Font.color
Без маржи
Это одна из основных концепций и наиболее ценные функции. В style-elements
нет полей, только отступы и новый атрибут spacing
.
padding
→ пробел между элементом и его содержимымspacing
→ пробел между дочерними элементами элемента
В этом примере отступ — это светло-серая область, а интервал — темно-серая область:
el [ Background.color lightGray , padding 20 ] <| row [ Background.color darkGray , spacing 20 ] [ box, box, box ]
Мы сохранили отступы и интервалы для двух отдельных элементов только для того, чтобы выделить их другим цветом. Обычно мы собирали их вместе вот так:
row [ padding 20 , spacing 20 ] [ box, box, box ]
Это очень простая концепция, которая отсутствует в CSS и значительно упрощает разработку внешнего интерфейса.
Нет CSS Grid, да CSS Flexbox (под капотом)
Под капотом — в новой версии 5 (все еще в альфа-версии) style-elements
— происходит много Flexbox. В восторге от того, что Internet Explorer в конце концов реализует CSS Grid в октябре 2017 года? Нет необходимости, style-elements
использует Flexbox для многих вещей.
Идея состоит в том, что каждая сетка, независимо от сложности, может быть построена из ряда строк и столбцов. А строки и столбцы создаются с помощью Flexbox.
Но как насчет медиа-запросов, которые могут перемещать контент внутри сетки? С помощью CSS Grid мы можем перетасовывать контент с помощью медиа-запросов по своему усмотрению. Но с Flexbox контроль ограничен.
Решение состоит в том, чтобы передать управление Elm. Поэтому, исходя из размера экрана, мы просто создаем новый макет.
Например, давайте посмотрим, как мы можем перетасовать элементы в сетке.
case device of Mobile -> column [] [ row [ A, B ] , row [ C, D ] ] Desktop -> column [] [ row [ D, A ] , row [ B, C ] ]
Или более распространенный вариант использования, когда мы показываем элементы в столбце для мобильных устройств и в строке для настольных компьютеров.
case device of Mobile -> column [] [ A, B ] Desktop -> row [] [ A, B ]
Другой пример
Предположим, мы хотим иметь слой поверх другого слоя. Например, мы хотим иметь счетчик после нажатия на кнопку.
В CSS мы можем использовать некоторый класс, который активирует некий псевдоэлемент с помощью :before
или :after
, а затем использует position = absolute
внутри элемента, имеющего position = relative
, и корректирует положение с помощью top
, bottom
, left
, right
. Хитрость CSS.
С style-elements
мы делаем:
el [ inFront True ( el [] <| text "↻" ) ] <| text "ciao"
так что inFront
— это атрибут, который заключает в себе набор трюков CSS для вас. Конечным результатом является то, что ↻ идет перед к ciao
.
Вывод
Это интересная концепция. Иногда спорный, но я считаю, что у этого есть потенциал.
Учтите также уровень абстракции поверх Javascript, предоставляемый Elm, и мы приблизимся к нирване.
Спасибо за чтение.