2 #concepts Basic concepts
Before reading the documentation, learn mlut basic concepts.
content/main.css
, line 341
2.1 #concepts.naming Naming algorithm
Almost all abbreviations in mlut are compiled by one algorithm. Below will be a simplified algorithm for compiling the abbreviations of the utilities names. Later it will be supplemented
- get all CSS properties that starts with one letter
- make ranking of them by popularity or alphabet if the popularity is not possible to calculate. Popularity for properties is calculated based on Chrome platforf statistic
- compose groups of properties that starts with one word. Select a group leader: repeating first word. Leader rating is the max rating of the property from group
- make abbreviations by the scheme below. Important notes:
- in descending order by rating, regardless of the relationship of the property to the group
- abbreviate the property, group leader or the first word property so that it does not intersect with already abbreviated properties
- subsequent abbreviations of all properties of the group and properties with the same initial word should begin with the same abbreviation, which was previously done
- if the group contains 2 or more subgroups (excluding logical:
block
,inline
), its leader is abbreviate by at least 2 letters:Fn
,Bd
- properties from 3 and less letters do not abbreviate:
Gap
,All
- properties and subproperties with physical directions have fixed abbreviations:
T
,R
,B
,L
,I
- subsequent words in properties are abbreviated by the same rules recursively
The one abbreviation scheme:
- the name must be abbreviate to the first letter of the source word.
- if the name is from several words, then every word is abbreviate to one letter
- if two names have the same first letter, then in the next name, when sorting them by the rating, the letter is added
- if the name is from several words, then the letter is added, depending on the name affiliation to the group
The order of adding the letter:
- consonant of the next syllable. If the next syllable begins to vowel, then we take the nearest previous consonant from it
- next consonant
- next vowel without a jump through the consonant
Examples you can see in the utils reference. More visual examples here will appear later.
content/main.css
, line 351
2.2 #concepts.util Utility
An entity that, depending on the parameters, does 1 action with the element styles. Utilities can change both one CSS property and several.
content/main.css
, line 386
2.2.1 #concepts.util.syntax Components syntax
The idea behind the components syntax is that the utility is divided into components, each of which corresponds to a part of a CSS rule. So the utilities consist of out:
- CSS at-rule: breakpoints,
@supports
, etc - pre-states - part of selector before the utility class name
- name
- value
- post-states - part of selector after the utility class name
Each part is separated by the lower underscore.
content/main.css
, line 396
2.2.2 #concepts.util.naming Naming
By origin, the utilities are:
- Common - named and work like CSS properties.
- Custom - affects several CSS properties or manages custom properties. Their names begin with a hyphen. All utilities that you will add, it is recommended to name as custom.
The names of utilities are written in upper CamelCase and can only contain letters. Thanks to the first capital letter, they are easy to add to an existing project without fear of name conflicts.
content/main.css
, line 415
2.2.3 #concepts.util.components Components
Under the hood of mlut, utilities are also parsed to components, but in a slightly different way. This is more relevant for working in AOT mode, but it will be useful for general understanding as well. This is how it works:
- at-rules
- pre-states
- post-states
- important:
!
modifier at the end of the utility value adds!important
to CSS - value: it can be a separate value, the name of the utility, group etc
Here is an example, as the utility will be parsed to the components:
@debug ml.parse-util('<sm_:f:>_D!_h::^sub');
// (
// 'at-rules': '<sm',
// 'pre-states': ':f:>',
// 'post-states': 'h::^sub',
// 'important': true,
// 'value': 'D',
// ),
Note that the order of components is important.
Most of the components in the mlut is convertible. This means that if the component or part of it correspond the rules of conversion, it will unfold into some CSS value. How to convert different components, you can read below in the relevant sections. If the mlut does not know how to convert the component, the behavior will depend on its type.
content/main.css
, line 430
2.2.3.1 #concepts.util.components.syntax Utility Generation Syntax (AOT)
Utility Generation Syntax - is the way to describe, with which components we want to generate utilities. It is similar to the syntax utilities in the final code, but has a number of differences:
- components of the same type are separated by spaces
- by default, the utilities with the components of each type are generated separately. It means that:
xl_^:h_Bdb_h,f
=>xl_Bdb
,^:h_Bdb
andBdb_f
- keywords are used, for explicit instructions, with what components we need utilities and not only:
BpAll ArSt _Bdb_h
This syntax is used in all places where utilities, utils groups, ranges, etc. are generated.
content/main.css
, line 461
2.3 #concepts.values Values
The values of utilities are almost arbitrary. That is, if the value is not converted, it appear in the CSS without changes.
To explicitly prevent conversion, use the =
before the value. Also, use = before
the value in quotes ''
: Ct='test'_af
, since in the future quotes will be used in the values without separator.
@include ml.mk-util('Ml', (5, 5exe, '=5'));
// CSS
.Ml5 {
margin-left: 5px;
}
.Ml5exe {
margin-left: 5exe;
}
.Ml\=5 {
margin-left: 5;
}
content/main.css
, line 474
2.3.1 #concepts.values.type Types
mlut has the following types of values that partially intersect with CSS data types. In the examples below will use a function that get a CSS value of the utility.
content/main.css
, line 503
2.3.1.1 #concepts.values.type.abbr Abbreviations
In the values of some utilities you can use the names of other utilities.
@debug ml.uv('Tsp-bdc'); // border-color
content/main.css
, line 577
2.3.1.2 #concepts.values.type.color Color
You can use both HEX colors and color names set by the user. Read more about adding your colors here. With colors, you can specify the opacity modifier *
. This converter is used to convert opacity. With modifier, you can use CSS variables or global keywords in any position:
@debug ml.uv('C#60c*20p'); // rgba(102, 0, 204, 0.2)
@debug ml.uv('C-red0*$co'); // rgba(204, 0, 102, var(--ml-co, 1))
If a variable is specified as opacity, then by default, it will have fallback 1
.
content/main.css
, line 542
2.3.1.3 #concepts.values.type.css_var CSS variables
Their names begin with $
written in lower camelCase and may contain numbers. They can be used almost everywhere, even as part of a complex value, for example in fractions:
@debug ml.uv('W1/$div'); // calc(1 / var(--ml-div) * 100%);
To specify a fallback, use ?
. In the fallback, you can specify any value, including another variable with fallback:
@debug ml.uv('W-$myCard?200'); // var(--ml-myCard, 200px)
@debug ml.uv('W-$myCard?$defWd?150'); // var(--ml-myCard, var(--ml-defWd, 150px))
content/main.css
, line 526
2.3.1.4 #concepts.values.type.gkw Global keywords
Similar to ordinary, but differ in that they can be used in any utility. You can add your global keywords in the settings. It is recommended to use the prefix, for example: gMyKw
. You can find the default mlut global keywords here.
@debug ml.uv('W-ih'); // inherit
content/main.css
, line 566
2.3.1.5 #concepts.values.type.kw Keywords
Keywords - abbreviations that comply with CSS keywords. They are written Camel Camel Case and may contain numbers. How to add your keywords look here.
@debug ml.uv('D-if'); // inline-flex
content/main.css
, line 555
2.3.1.6 #concepts.values.type.number Number
Numbers can be both with units of measurements and without. Float values are allowed, and fractions also can be used in the default conversion type:
@debug ml.uv('Fnw100'); // 100
@debug ml.uv('Ml3r'); // 3rem
@debug ml.uv('W1/4'); // 25%
content/main.css
, line 513
2.3.2 #concepts.values.convert Conversion type
In different utilities, the values will be converted in different ways. Conversion type is a rule by which the value will be converted. It consists of a sequence of converters and keywords. Conversion type is specified in the conversion
option of utilities. For details on conversion and existing types, see here.
content/main.css
, line 588
2.3.3 #concepts.values.multi Multiple values
For any utility you can specify multiple values. Instead of a blank used ;
:
@debug ml.uv('Bd3;sec0;d'); // 3px #0c6 dotted
In some utilities, you can specify several lists of values. To do this, use the same separator as in CSS: /
or ,
@debug ml.uv('Bdrd1r;2/5p'); // 1rem 2px / 5%
The separator for multi-list is specified in the multi-list-separator
utility option. Please note that each value is converted separately. The prevent-conversion token =
also applies to each value in the list separately:
@debug ml.uv('M1r;=10x'); // 1rem 10x
content/main.css
, line 598
2.3.4 #concepts.values.sep Separators
Depending on the value type, different separators between the name and value of the utility are used. By default, only for strings without quotes (including empty) and CSS variables, the separator -
are used: Txd-u
, C-$prime
. For all other values, separators are not used: W100p
, Fnw700
, but you can set them in the settings.
=
token will also be a separator if you want to prevent conversion: -Mut=5
.
content/main.css
, line 619
2.3.5 #concepts.values.important CSS important
At the end of the value or their sequences, you can specify !
which will add the CSS !important
to the final value. If the utility affects several properties, then !important
adds to each.
@include ml.apply('M2r;12! -I2r!');
// CSS
.M2r\;12\! {
margin: 2rem 12px !important;
}
.-I2r! {
top: 2rem !important;
right: 2rem !important;
bottom: 2rem !important;
left: 2rem !important;
}
content/main.css
, line 631
2.3.6 #concepts.values.negation Negation
The negation is denoted by -
before the value and works everywhere where it is appropriate. With numbers, with CSS variables and with keywords, if the final value may be negative.
@include ml.mk-util('Ml', ('2/-8', -0.7, '-$myVar'));
// CSS
.Ml2\/-8 {
margin-left: -25%;
}
.Ml-0\.7 {
margin-left: -0.7rem;
}
.Ml--\$myVar {
margin-left: calc(var(--ml-myVar) * -1);
}
content/main.css
, line 656
2.4 #concepts.at_rules At-rules
At-rules component may consist of breakpoints and rules. To specify breakpoint, just write it name: lg_D-f
. To add rule, specify @
before its name: @s:ctv_D-g
. Breakpoints can only be specified 1 time in the entire component and only at the beginning, and rules - as much as you need.
@include ml.mk-util('D', ('xl_', '@s:ctv_g'));
// CSS
@media (min-width: 1200px) {
.xl_D {
display: block;
}
}
@supports (content-visibility: auto) {
.\@s\:ctv_D-g {
display: grid;
}
}
In all at-rules, you can create complex conditions using the :
and ,
operators, which corresponds and
and or
in CSS. In some examples below, functions for at-rules conversion will be used for brevity.
@debug ml.convert-ar-media('pr:h>gSm:dm,p-c:w>=90r'); // print and (min-height: #{ml.bp(sm) + 1}) and (display-mode: fullscreen), (pointer: coarse) and (min-width: 90rem)
And of course, Rules can be used in any order and in any combination.
content/main.css
, line 682
2.4.1 #concepts.at_rules.bp Breakpoints
The width of the screen on which the styles change. The default mobile-first approach is used, so breakpoints are converted to min-width
media queries. How to configure breakpoints see here.
If required max-width
, add the <
before the breakpoint:
@debug ml.convert-ar-bp('<sm'); // (max-width: 519px)
Or use operators to create a range:
@debug ml.convert-ar-bp('sm:md,xl'); // (min-width: 520px) and (max-width: 767px), (min-width: 1200px)
content/main.css
, line 714
2.4.2 #concepts.at_rules.container @container
With the @container rule you can use both generic and named container queries
@include ml.apply('@c:w>600_C-red');
@include ml.apply('@c:box:h>20r_P5u');
// CSS
@container (min-width: 601px) {
.\@c\:w\>600_C-red {
color: red;
}
}
@container box (max-height: 20rem) {
.\@c\:box\:h\<\=20r_P5u {
padding: 1.25rem;
}
}
content/main.css
, line 829
2.4.3 #concepts.at_rules.layer @layer
With the @layer rule, you can put some utils to different cascade layers
@include ml.apply('@l:utils_C-red');
// CSS
@layer utils {
.\@l\:utils_C-red {
color: red;
}
}
content/main.css
, line 810
2.4.4 #concepts.at_rules.media @media
In @media rule, you can use the type, features and custom queries. There are two media types:
pr
-print
s
-screen
@media
is the default rule. To choose it, just write @
and then specify queries. The default rule can be selected in the settings.
@include ml.mk-util('@:w>=gSm:o _D', 'if');
// CSS
@media (min-width: 520px) and (orientation: landscape) {
.\@\:w\>\=gSm\:o_D-if {
display: inline-flex;
}
}
content/main.css
, line 731
2.4.4.1 #concepts.at_rules.media.feat Media features
Work almost as well as utilities. Key differences:
- if the feature has only two values, then to check its presence, you can simply write a name. For checking lack, you can use the
none
keyword. Note that some features also have the default value. - if the features can check the range of values, then you can use the range syntax from The Media Queries Level 4
@debug ml.convert-ar-media('ah'); // (any-hover)
@debug ml.convert-ar-media('h-n'); // (hover: none)
@debug ml.convert-ar-media('dm'); // (display-mode: fullscreen)
@debug ml.convert-ar-media('c<256'); // (max-color: 255)
content/main.css
, line 753
2.4.5 #concepts.at_rules.supports @supports
In @supports rule, you can check the support of properties and values of any utility from the registry. To check the current value of the utility used, leave the rule blank.
@include ml.mk-util('Ps', '@s:d-flr_sk');
@include ml.mk-util('D', '@s_f');
// CSS
@supports (display: flow-root) {
.\@s\:d-flr_Ps-sk {
position: sticky;
}
}
@supports (display: flex) {
.\@s_D-f {
display: flex;
}
}
To check the property, it is not necessary to specify the value:
@debug ml.convert-ar-supports('apcr'); // (aspect-ratio: initial)
You can also use this-utility alias &
in a complex condition.
@debug ml.convert-ar-supports('d-ig:&', ('name': 'Jc', 'value': '-se'); // (display: inline-grid) and (justify-content: space-evenly)
To check the lack of support, add an operator !
before the utility:
@debug ml.convert-ar-supports('!d-ig'); // (not (display: inline-grid))
Please note that in one supports rule, only one type of the operator is supported for a combination of expressions. When using both immediately, an error will appear
@debug ml.convert-ar-supports('ps-sc,h1vh:m-a'); // ERROR: Different operators are not allowed in one abbreviations list
content/main.css
, line 769
2.4.6 #concepts.at_rules.custom Custom expressions
You can add custom expressions to any at-rule. Regardless of the name you specify, custom expressions always begin with -
. See here how to add it.
content/main.css
, line 855
2.5 #concepts.states States
In the states you can use pseudo-class, pseudo-elements and almost everything that CSS selectors allow. States are two types: pre
and post
, depending on the position in the CSS utility selector. In both of them, you can use the same parts.
@include ml.mk-util(':h _D_ af', 'f');
// CSS
.D-f {
display: flex;
}
:hover .\:h_D-f {
display: flex;
}
.D-f_af::after {
display: flex;
}
In essence, the states is a simplified CSS selector list. To combine the states, use :
, and for the separation of selector to the lists - ,
. For a space in the selector, use ::
or :
if post-state is the first in the list.
@include ml.mk-util('D_ h,f h:b :fc', '');
// CSS
...
.D_h\,f:hover,
.D_h\,f:focus {
display: block;
}
.D_h\:b:hover::before {
display: block;
}
.D_\:fc :first-child {
display: block;
}
You can use almost arbitrary parts in any order: combinators, classes, etc. In terms of conversion, the states are similar to the values of utilities:
- unconvertible parts will fall into the selector unchanged
- use
=
to prevent conversion
@include ml.mk-util('=a. h1+ _D_ .js:a', '');
// CSS
...
a.\=a\._D {
display: block;
}
h1 + .h1\+_D {
display: block;
}
.D_\.js\:a.js:active {
display: block;
}
Full list of existing states see in the configuration.
content/main.css
, line 865
2.5.1 #concepts.states.special Special states
There are several special states that are converted by a special way.
content/main.css
, line 934
2.5.1.1 #concepts.states.special.ctx Context
With the help of a context, the utilities can react to the state of the container, adjacent item etc. It is denoted by ^
and is just an alias for .-Ctx
. Add this class to markup, and in the states of utilities, make a combination for the necessary behavior.
You can also specify the name of the context. Allowed lower camelCase and numbers.
@include ml.mk-util('^:h ^one:lc:>_D', 'f');
// CSS
...
.-Ctx:hover .\^\:h_D-f {
display: flex;
}
.-Ctx-one:last-child > .\^one\:lc\>_D-f {
display: flex;
}
content/main.css
, line 942
2.5.1.2 #concepts.states.special.not Not
To use a pseudo-class not
, add !
before any part of state:
@include ml.mk-util('D_!fc !input', '');
// CSS
...
.D_\!fc:not(:first-child) {
display: block;
}
.D_\!input:not(input) {
display: block;
}
content/main.css
, line 966
2.5.1.3 #concepts.states.special.tu This utility alias
As in @supports, &
can be used in the states. To increase specificity, it can only be used in post-states so many times as much as you need:
@include ml.apply('D_&');
// CSS
...
.D_\&.D_\& {
display: block;
}
content/main.css
, line 988
2.5.2 #concepts.states.custom Custom states
Works similarly as the custom at-rules expressions, see more here.
content/main.css
, line 1006
2.6 #concepts.custom_unit Custom units of measure
In mlut there are 3 custom units:
u
- space unitgg
- grid guttergc
- grid column. Used only in the legacy grid-system
You can set the custom units values in the settings.
content/main.css
, line 1016
2.6.1 #concepts.custom_unit.gg Grid gutter
The value of this unit depends on the CSS variable --ml-gg
. Due to this, it value can be changed dynamically. By default --ml-gg = 3u
but increase to 4u
on the lg
breakpoint.
@debug ml.uv('Ml-2.5gg'); // calc(var(--ml-gg) * -2.5)
content/main.css
, line 1042
2.6.2 #concepts.custom_unit.su Space unit
Unit of measurement to create a scale of sizes and indents in your design system. By default 1u = 0.25rem
(4px).
@debug ml.uv('Fns6u'); // 1.5rem
content/main.css
, line 1031