Помните, я сказал вам, что отделение макета от стиля — это хорошо? Ну забудь об этом!

Важным является не разделение макета и стиля, а скорее

Уровень абстракции поверх 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-colorBorder.color
  • background-colorBackground.color

Остальные немного отличаются

  • colorFont.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, и мы приблизимся к нирване.

Спасибо за чтение.