Define CSS in Elm.
input
[ type_ "checkbox"
, name "toggle-all"
, checked allCompleted
, onClick (CheckAll (not allCompleted))
, css
[ property "position" "absolute"
, property "top" "-55px"
, property "left" "-12px"
, property "width" "60px"
, property "height" "34px"
, property "text-align" "center"
, property "border" "none" -- Mobile Safari
, withPseudoElement "before"
[ property "content" <| qt "❯"
, property "font-size" "22px"
, property "color" "#e6e6e6"
, property "padding" "10px 27px 10px 27px"
]
, with (pseudoElement [ pseudoClass "checked" ] "before")
[ property "color" "#737373" ]
, -- Hack to remove background from Mobile Safari.
-- Can't use it globally since it destroys checkboxes in Firefox
withMedia "screen and (-webkit-min-device-pixel-ratio:0)"
[ property "background" "none"
, property "-webkit-transform" "rotate(90deg)"
, property "transform" "rotate(90deg)"
, property "-webkit-appearance" "none"
, property "appearance" "none"
]
]
]
[]examples/TodoMVCevancz/elm-todomvccss and basic functionslabel
[ css
[ property "white-space" "pre-line"
, property "word-break" "break-all"
, property "padding" "15px 60px 15px 15px"
, property "margin-left" "45px"
, property "display" "block"
, property "line-height" "1.2"
, property "transition" "color 0.4s"
, if todo.completed then
batch
[ property "color" "#d9d9d9"
, property "text-decoration" "line-through"
]
else
noStyle
]
, onDoubleClick (EditingEntry todo.id True)
]
[ text todo.description ]Create a property style.
css [ property "-webkit-font-smoothing" "none" ]...outputs
-webkit-font-smoothing: none;Create a batched style.
underlineOnHover =
batch
[ textDecoration none
, hover
[ textDecoration underline ]
]
css
[ color (rgb 128 64 32)
, underlineOnHover
]...has the same result as:
css
[ color (rgb 128 64 32)
, textDecoration none
, hover
[ textDecoration underline ]
]Create an empty style.
if predicate then
property "key" "value"
else
noStyleOrigami.Html.HtmlはHtml.Htmlと同じように扱えますOrigami.Html.toHtmlなどを使ってHtml.Htmlに変換してくださいtoHtmlなどでcssで適用されているstyleが収集されてstyle tagを生成しますlabelに適用されたstyleは以下のようにstyle tag内に書き出されます._1e7eb6f2 {
white-space: pre-line;
word-break: break-all;
padding: 15px 60px 15px 15px;
margin-left: 45px;
display: block;
line-height: 1.2;
transition: color 0.4s;
}label側は以下のように記述されたのと同様になります
label
[ class "_1e7eb6f2"
, onDoubleClick (EditingEntry todo.id True)
]
[ text todo.description ]_1e7eb6f2というクラス名が付与されていますbutton
[ css
[ property "display" "none"
, property "position" "absolute"
, property "top" "0"
, property "right" "10px"
, property "bottom" "0"
, property "width" "40px"
, property "height" "40px"
, property "margin" "auto 0"
, property "font-size" "30px"
, property "color" "#cc9a9a"
, property "margin-bottom" "11px"
, property "transition" "color 0.2s ease-out"
, withPseudoClass "hover" [ property "color" "#af5b5e" ]
, withPseudoElement "after" [ property "content" "'×'" ]
]
, onClick (Delete todo.id)
]
[]これは以下のように書き出されます
._b75a75af {
display: none;
position: absolute;
top: 0;
right: 10px;
bottom: 0;
width: 40px;
height: 40px;
margin: auto 0;
font-size: 30px;
color: #cc9a9a;
margin-bottom: 11px;
transition: color 0.2s ease-out;
}
_b75a75af:hover {
color: #af5b5e;
}
._b75a75af::after {
content: '×';
}Nest with a class selector.
css [ withClass "classname" [ property "key" "value" ] ]...outputs
_xxx.classname {
key: value;
}Nest with a attribute selector.
css [ withAttribute """href="https://example.org"""" [ property "key" "value" ] ]...outputs
_xxx[href="https://example.org"] {
key: value;
}Nest with a pseudo class.
css [ withPseudoClass "hover" [ property "key" "value" ] ]...outputs
_xxx:hover {
key: value;
}Nest with a pseudo element.
css [ withPseudoElement "after" [ property "content" <| qt "×" ] ]...outputs
_xxx::after {
content: "×";
}note: withPseudoElementを使ったらそれ以上ネストできません
css
[ withPseudoElement "after"
[ property "content" <| qt "×"
, withClass "notAllowed"
[ property "color" "white" ]
]
]...outputs
_xxx::after {
content: "×";
}結合子も使用することができます
footer
[ css
[ property "margin" "65px auto 0"
, property "color" "#bfbfbf"
, property "font-size" "10px"
, property "text-shadow" "0 1px 0 rgba(255, 255, 255, 0.5)"
, property "text-align" "center"
, withDescendants [ tag "p" ] [ property "line-height" "1" ]
, withDescendants [ tag "a" ]
[ property "color" "inherit"
, property "text-decoration" "none"
, property "font-weight" "400"
, withPseudoClass "hover" [ property "text-decoration" "underline" ]
]
]
] [...]...outputs
._89167f0f {
margin: 65px auto 0;
color: #bfbfbf;
font-size: 10px;
text-shadow: 0 1px 0 rgba(255, 255, 255, 0.5);
text-align: center;
}
._89167f0f p {
line-height: 1;
}
._89167f0f a {
color: inherit;
text-decoration: none;
font-weight: 400;
}tag関数を使って対象のタグを複数指定することができますNest with descendant combinators.
css [ withDescendants [ tag "p", tag "li" ] [ property "key" "value" ] ]...outputs
_xxx p, _xxx li {
key: value;
}Nest with child combinators.
css [ withChildren [ tag "p", tag "li" ] [ property "key" "value" ] ]...outputs
_xxx > p, _xxx > li {
key: value;
}Nest with general sibling combinators.
css [ withGeneralSiblings [ tag "p", tag "li" ] [ property "key" "value" ] ]...outputs
_xxx ~ p, _xxx ~ li {
key: value;
}Nest with adjacent sibling combinators.
css [ withAdjacentSiblings [ tag "p", tag "li" ] [ property "key" "value" ] ]...outputs
_xxx + p, _xxx + li {
key: value;
}Represent an element selector.
tag "p"...outputs
pRepresent a universal selector.
everyTag...outputs
*note: もし.parent > .childのようなselectorを使用したいと思っているなら.parent > *.childのように暗黙に全称セレクターが指定されていると思ってeveryTagを使ってください
ul
[ css
[ property "margin" "0"
, property "padding" "0"
, property "list-style" "none"
, property "position" "absolute"
, property "right" "0"
, property "left" "0"
, withMedia "(max-width: 430px)" [ property "bottom" "10px" ]
]
] [..]...outputs
._a85c725b {
margin: 0;
padding: 0;
list-style: none;
position: absolute;
right: 0;
left: 0;
}
@media (max-width: 430px) {
._a85c725b {
bottom: 10px;
}
}Nest with a media query.
css [ withMedia "screen" [ property "key" "value" ] ]...outputs
@media screen {
_xxx {
key: value;
}
}note: Media Queryを複数回入れ子にすることはできません
css
[ withMedia "screen"
[ property "key" "value"
, withMedia "not nestable" [ property "key" "value" ]
, withClass "nestable" [ property "key" "value" ]
]
]..outputs
@media screen {
_xxx {
key: value;
}
}
@media screen {
_xxx.nestable {
key: value;
}
}@mediaが複数書き出されますwithXxx関数で大体のことには事足りるかと思いますSelectorを学びましょう ┌ child ┌ descendant ┌ adjacent sibling
class │ pseudo class │ attribute │ pseudo element
┌────┐ ┌─┐┌──────────────┐┌──────┐┌───────────────────┐ ┌─┐┌─────┐
._xxx.class > *:nth-child(2n+1) section[aria-hidden="false"], ._xxx + *::after {...}
└──────────────────────────────────────────────────────────┘ └──────────────┘
selector selectorRepeatableSelectorとしてまとめていますSelector型を生成するselector関数はRepeatableSelectorのListを受け取るようになっていますpseudoElementを使ってくださいSelectorはwith, withEach, withCustomでcss関数に繋げられますSelectorを列挙したければwithEachかwithCustomを使ってくださいwithCustomにはMedia Queryも付加することができますNest with a Selector.
css
[ with (selector [ class "classname" ]) [ property "key" "value" ] ]...outputs
_xxx.classname {
key: value;
}Nest with Selector list.
css
[ withEach
[ selector [ class "classname" ]
, selector [ attribute "title" ]
]
[ property "key" "value" ]
]...outputs
_xxx.classname, _xxx[title] {
key: value;
}note: もし空リストを与えたらそのstyleは霧視されます
css
[ withEach [] [ property "key" "empty-value" ]
, property "key" "value"
]...outputs
_xxx {
key: value;
}Nest with Selector list and a media query.
css
[ withCustom "(max-width: 430px)"
[ selector [ class "classname" ]
, selector [ attribute "title" ]
]
[ property "key" "value" ]
]...outputs
@media (max-width: 430px) {
_xxx.classname, _xxx[title] {
key: value;
}
}type RepeatableSelector
= ClassSelector String
| PseudoClassSelector String
| AttributeSelector String
| DescendantCombinator Tag
| ChildCombinator Tag
| GeneralSiblingCombinator Tag
| AdjacentSiblingCombinator TagRepresent a class selector.
class "classname"...outputs
.classnameRepresent a pseudo class.
pseudoClass "hover"...outputs
:hoverRepresent an attribute selector.
attribute "aria-hidden=\"false\""...outputs
[aria-hidden="false"]Represent a descendant combinator with a type selector or universal selector.
descendant (tag "p")...outputs
pRepresent a child combinator with a type selector or universal selector.
child (tag "li")...outputs
> liRepresent a general sibling combinator with a type selector or universal selector.
generalSibling everyTag...outputs
~ *Represent a adjacent sibling combinator with a type selector or universal selector.
adjacentSibling (tag "section")...outputs
+ sectionbatch
[ property "border-radius" "50px"
, property "width" "50px"
, -- [Copyright (c) 2019 Epicmax LLC](https://epic-spinners.epicmax.co/)
withEach [ pseudoElement [] "after", pseudoElement [] "before" ]
[ property "content" <| qt ""
, property "position" "absolute"
, property "width" "60%"
, property "height" "60%"
, property "border-radius" "100%"
, property "border" "calc(30px / 10) solid transparent"
, animation
[ ( ( from, [] ), [ propertyA "transform" "rotate(0deg)" ] )
, ( ( to, [] ), [ propertyA "transform" "rotate(360deg)" ] )
]
, property "animation-duration" "1s"
, property "animation-iteration-count" "infinite"
]
, withPseudoElement "after" [ property "border-top-color" "#ffe9ef" ]
, withPseudoElement "before"
[ property "border-bottom-color" "#ffe9ef"
, property "animation-direction" "alternate"
]
]Define a animation.
css
[ animation
[ ( ( from, [] ), [ propertyA "key" "value" ] )
, ( ( pct 20, [ pct 80 ] ), [ propertyA "key" "value" ] )
, ( ( to, [] ), [ propertyA "key" "value" ] )
]
]...outputs
.hashed-class-name {
animation-name: hashed-animation-name;
}
@keyframes hashed-animation-name {
from {
key: value;
}
20%, 80% {
key: value;
}
to {
key: value;
}
}animation-name propertyが暗黙に生成されますpropertypropertyとは型が違うSelectors for animation.
from, to and pct(%).
from token.
to token.
30%, 70% and so on.
For use with font-family and so on.
property "font-family" (qt "Gill Sans Extrabold")div []
[ div [ css [ property "key" "value" ] ] []
, div [ css [ property "key" "value" ] ] []
, div [] [ div [ css [ property "key" "value" ] ] [] ]
]...outputs only
._xxx {
key: value;
}cssに適用したstyleの単位で行われますcss関数を複数使ったらどうなる?div
[ css [ property "display" "none" ]
, css [ property "display" "block" ]
]
[ text "表示されますか?" ]css関数でまとめられた単位で扱われ、Dictを経由して書き出されますccsを使う順番に依存した実装は行わないほうがいいでしょうcssの値を上書きしたいのならばwithClassなどを使ってセレクターの詳細度を上げるとよいでしょうcssWithClass : String -> List Style -> Attribute msg
cssWithClass classname styles =
batchAttributes [ Attributes.class classname, css [ withClass classname styles ] ]