Syntax¶
Description: state
is defined as any pseudo-class that alters the state of an element.
ctr('<#selector>', {
state: {
option: {
key: '<identifier>'
delay: '<value>' | 0s
duration: '<value>' | 0.5s
property: '<string>' | <list> | <scope:properties>
ease: '<value>' | cubic-bezier(0.42, 0, 0.58, 1)
}
on: {
<property:A>: <...>
<property:B>: <...>
}
non: {
<property:A>: <...>
<property:B>: <...>
}
}
})
<#selector>:
state:
option:
key: <identifier>
delay: <value> | 0s
duration: <value> | 0.5s
property: <string> | <list> | <scope:properties>
ease: <value> | cubic-bezier(0.42, 0, 0.58, 1)
on:
<property:A>: <...>
<property:B>: <...>
non:
<property:A>: <...>
<property:B>: <...>
<#selector>:<identifier> {
<property:A>: <...>;
<property:B>: <...>;
transition-delay: 0s, 0s;
transition-duration: 0.5s, 0.5s;
transition-property: <property:A>, <property:B>;
transition-timing-function: cubic-bezier(0.42, 0, 0.58, 1), cubic-bezier(0.42, 0, 0.58, 1);
}
<#selector>:not(<identifier>) {
<property:A>: <...>;
<property:B>: <...>;
transition-delay: 0s, 0s;
transition-duration: 0.5s, 0.5s;
transition-property: <property:A>, <property:B>;
transition-timing-function: cubic-bezier(0.42, 0, 0.58, 1), cubic-bezier(0.42, 0, 0.58, 1);
}
ctr('<#selector>', {
// State Identifier
<identifier>: {
on: {
<property:A>: <...>
<property:B>: <...>
}
non: {
<property:A>: <...>
<property:B>: <...>
}
}
})
<#selector>:
# State Identifier
<identifier>:
on:
<property:A>: <...>
<property:B>: <...>
non:
<property:A>: <...>
<property:B>: <...>
<#selector>:<identifier> {
<property:A>: <...>;
<property:B>: <...>;
}
<#selector>:not(<identifier>) {
<property:A>: <...>;
<property:B>: <...>;
}
Notes
- State-altering pseudo-classes:
active
-checked
-disabled
-enabled
-focus
-in-range
-hover
invalid
-link
-optional
-out-of-range
-required
-valid
-visited
- If you are using any other pseudo-class or pseudo-element use the
element
feature
- Regex:
^states$|^state$|^state-|^customSt|^hover$|^hover-|^focus$|^focus-|^active$|^active-|^checked$|^checked-|^link$|^link-|^visited$|^visited-|^valid$|^valid-|^required$|^required-|^out-of-range$|^out-of-range-|^optional$|^optional-|^invalid$|^invalid-|^in-range$|^in-range-|^enabled$|^enabled-|^disabled$|^disabled-/i
- It would be in your best interest to review
transition
feature before you dive intostate
- For the sake of brevity, I use the State Key syntax of
hover
rather than specifying astate
Object with akey
property to define the<identifier>
- MDN Pseudo-classes
On¶
Description: An on
Object in a state
creates a pseudo-class condition for the <identifier>
and transition properties for the enclosed CSS.
ctr('.test', {
width: 200px
hover: {
on: {
opacity: 1
height: 400px
}
}
})
.test:
width: 200px
hover:
on:
opacity: 1
height: 400px
.test {
width: 200px;
}
.test:hover {
opacity: 1;
height: 400px;
transition-delay: 0s, 0s;
transition-duration: 0.5s, 0.5s;
transition-property: opacity, height;
transition-timing-function: cubic-bezier(0.42, 0, 0.58, 1), cubic-bezier(0.42, 0, 0.58, 1);
}
ctr('.test', {
width: 200px
hover: {
on: {
opacity: 1
height: 400px
}
}
})
.test {
width: 200px;
}
.test:hover {
opacity: 1;
height: 400px;
transition-delay: 0s, 0s;
transition-duration: 0.5s, 0.5s;
transition-property: opacity, height;
transition-timing-function: cubic-bezier(0.42, 0, 0.58, 1), cubic-bezier(0.42, 0, 0.58, 1);
}
.test:
width: 200px
hover:
on:
opacity: 1
height: 400px
Notes
- Think of an
on
Object like a feature unto itself in that it works with other features such asmedia
,element
, and the like
Non¶
Description: A non
Object in a state
creates a negation pseudo-class condition for the <identifier>
and transition properties for the enclosed CSS.
ctr('.test', {
width: 200px
hover: {
non: {
opacity: 1
height: 400px
}
}
})
.test:
width: 200px
hover:
non:
opacity: 1
height: 400px
.test {
width: 200px;
}
.test:not(:hover) {
opacity: 1;
height: 400px;
transition-delay: 0s, 0s;
transition-duration: 0.5s, 0.5s;
transition-property: opacity, height;
transition-timing-function: cubic-bezier(0.42, 0, 0.58, 1), cubic-bezier(0.42, 0, 0.58, 1);
}
ctr('.test', {
width: 200px
hover: {
non: {
opacity: 1
height: 400px
}
}
})
.test {
width: 200px;
}
.test:not(:hover) {
opacity: 1;
height: 400px;
transition-delay: 0s, 0s;
transition-duration: 0.5s, 0.5s;
transition-property: opacity, height;
transition-timing-function: cubic-bezier(0.42, 0, 0.58, 1), cubic-bezier(0.42, 0, 0.58, 1);
}
.test:
width: 200px
hover:
non:
opacity: 1
height: 400px
Notes
- Think of a
non
Object like a feature unto itself in that it works with other features such asmedia
,element
, and the like- Underneath the hood of the
state
,non
is masquerading as a context-awarenon
feature which will create transition properties
- Underneath the hood of the
Static¶
Description: A static
Object in a state
creates a pseudo-class condition and a matching negation condition, absent of transition properties, for the enclosed CSS regardless of the <identifier>
. Additionally, a static
Object can be defined in an auxiliary state Object to omit the generation of transition properties.
ctr('.test', {
width: 200px
hover: {
static: {
opacity: 1
height: 400px
}
}
})
.test:
width: 200px
hover:
static:
opacity: 1
height: 400px
.test {
width: 200px;
}
.test:hover {
opacity: 1;
height: 400px;
}
.test:not(:hover) {
opacity: 1;
height: 400px;
}
ctr('.test', {
width: 200px
hover: {
static: {
opacity: 1
height: 400px
}
}
})
.test {
width: 200px;
}
.test:hover {
opacity: 1;
height: 400px;
}
.test:not(:hover) {
opacity: 1;
height: 400px;
}
.test:
width: 200px
hover:
static:
opacity: 1
height: 400px
ctr('.test', {
width: 200px
hover: {
// in an auxiliary state
on: {
height: 400px
static: {
opacity: 1
}
}
}
})
.test:
width: 200px
hover:
# in an auxiliary state
on:
height: 400px
static:
opacity: 1
.test {
width: 200px;
}
.test:hover {
opacity: 1;
height: 400px;
transition-delay: 0s;
transition-duration: 0.5s;
transition-property: height;
transition-timing-function: cubic-bezier(0.42, 0, 0.58, 1);
}
ctr('.test', {
width: 200px
hover: {
// in an auxiliary state
on: {
height: 400px
static: {
opacity: 1
}
}
}
})
.test {
width: 200px;
}
.test:hover {
opacity: 1;
height: 400px;
transition-delay: 0s;
transition-duration: 0.5s;
transition-property: height;
transition-timing-function: cubic-bezier(0.42, 0, 0.58, 1);
}
.test:
width: 200px
hover:
# in an auxiliary state
on:
height: 400px
static:
opacity: 1
Notes
- Auxiliary states:
on
,non
,common
, andstatic
- The CSS folks who reside in tall ivory towers will cringe upon the use of
static
, but we live in a world full of semantic-shantics so if it does the trick, to hell with them
Static Identifier¶
Description: Any state
<identifier>
defined in global option stateOmitList
is considered a static <identifier>
and no transition properties are generated for the enclosed CSS.
ctr('.test', {
width: 200px
link: {
on: {
color: red
}
non: {
color: blue
}
}
})
.test:
width: 200px
link:
on:
color: red
non:
color: blue
.test {
width: 200px;
}
.test:link {
color: #f00;
}
.test:not(:link) {
color: #00f;
}
ctr('.test', {
width: 200px
link: {
on: {
color: red
}
non: {
color: blue
}
}
})
.test {
width: 200px;
}
.test:link {
color: #f00;
}
.test:not(:link) {
color: #00f;
}
.test:
width: 200px
link:
on:
color: red
non:
color: blue
Notes
- Default
stateOmitList
:link
,optional
,required
, andvalid
- This behavior can also be altered locally through the
autoGen
option
property
Common¶
Description: A common
Object in a state
creates a pseudo-class condition and a matching negation condition for the <identifier>
.
ctr('.test', {
width: 200px
hover: {
// merged into both on and non
common: {
option: {
duration: 1s
}
transform: {
translateZ: 0
}
}
on: {
transform: {
translateY: 20
}
}
non: {
transform: {
translateY: 0
}
}
}
})
.test:
width: 200px
hover:
# merged into both on and non
common:
option:
duration: 1s
transform:
translateZ: 0
on:
transform:
translateY: 20
non:
transform:
translateY: 0
.test {
width: 200px;
}
.test:hover {
transition-delay: 0s;
transition-duration: 1s;
transition-property: transform;
transform: translateZ(0) translateY(20);
transition-timing-function: cubic-bezier(0.42, 0, 0.58, 1);
}
.test:not(:hover) {
transition-delay: 0s;
transition-duration: 1s;
transition-property: transform;
transform: translateZ(0) translateY(0);
transition-timing-function: cubic-bezier(0.42, 0, 0.58, 1);
}
ctr('.test', {
width: 200px
hover: {
// merged into both on and non
common: {
option: {
duration: 1s
}
transform: {
translateZ: 0
}
}
on: {
transform: {
translateY: 20
}
}
non: {
transform: {
translateY: 0
}
}
}
})
.test {
width: 200px;
}
.test:hover {
transition-delay: 0s;
transition-duration: 1s;
transition-property: transform;
transform: translateZ(0) translateY(20);
transition-timing-function: cubic-bezier(0.42, 0, 0.58, 1);
}
.test:not(:hover) {
transition-delay: 0s;
transition-duration: 1s;
transition-property: transform;
transform: translateZ(0) translateY(0);
transition-timing-function: cubic-bezier(0.42, 0, 0.58, 1);
}
.test:
width: 200px
hover:
# merged into both on and non
common:
option:
duration: 1s
transform:
translateZ: 0
on:
transform:
translateY: 20
non:
transform:
translateY: 0
Notes
transform
Object helper- The
common
Object is deep merged into eachstate
auxiliary Object - The difference between the
common
andoption
Object is that you can specify CSS properties incommon
Option¶
Description: An option
Object in a state
, on
, non
, or common
Object alters the default transition values in the scope it is defined.
ctr('.test', {
width: 200px
hover: {
// option values applied to both on and non
option: {
// transition-duration
duration: 1s
// transition-delay
delay: 0.5s
// transition-timing-function
ease: 'ease-in'
}
on: {
background: red
opacity: 1
}
non: {
background: blue
opacity: 0.5
}
}
})
.test:
width: 200px
hover:
# option values applied to both on and non
option:
# transition-duration
duration: 1s
# transition-delay
delay: 0.5s
# transition-timing-function
ease: ease-in
on:
background: red
opacity: 1
non:
background: blue
opacity: 0.5
.test {
width: 200px;
}
.test:hover {
opacity: 1;
background: #f00;
transition-duration: 1s, 1s;
transition-delay: 0.5s, 0.5s;
transition-property: background, opacity;
transition-timing-function: ease-in, ease-in;
}
.test:not(:hover) {
opacity: 0.5;
background: #00f;
transition-duration: 1s, 1s;
transition-delay: 0.5s, 0.5s;
transition-property: background, opacity;
transition-timing-function: ease-in, ease-in;
}
ctr('.test', {
width: 200px
hover: {
// option values applied to both on and non
option: {
// transition-duration
duration: 1s
// transition-delay
delay: 0.5s
// transition-timing-function
ease: 'ease-in'
}
on: {
background: red
opacity: 1
}
non: {
background: blue
opacity: 0.5
}
}
})
.test {
width: 200px;
}
.test:hover {
opacity: 1;
background: #f00;
transition-duration: 1s, 1s;
transition-delay: 0.5s, 0.5s;
transition-property: background, opacity;
transition-timing-function: ease-in, ease-in;
}
.test:not(:hover) {
opacity: 0.5;
background: #00f;
transition-duration: 1s, 1s;
transition-delay: 0.5s, 0.5s;
transition-property: background, opacity;
transition-timing-function: ease-in, ease-in;
}
.test:
width: 200px
hover:
# option values applied to both on and non
option:
# transition-duration
duration: 1s
# transition-delay
delay: 0.5s
# transition-timing-function
ease: ease-in
on:
background: red
opacity: 1
non:
background: blue
opacity: 0.5
ctr('.test', {
width: 200px
hover: {
// applied to both on and non
option: {
ease: 'ease-in'
delay: 0.25s
}
on: {
// option values only applied to on
option: {
duration: 1s
}
opacity: 1
background: red
}
non: {
// option values only applied to non
option: {
duration: 2s
// overrides option
ease: 'ease-out'
}
opacity: 0.5
background: blue
}
}
})
.test:
width: 200px
hover:
# applied to both on and non
option:
ease: ease-in
delay: 0.25s
on:
# option values only applied to on
option:
duration: 1s
opacity: 1
background: red
non:
# option values only applied to non
option:
duration: 2s
# overrides option
ease: ease-out
opacity: 0.5
background: blue
.test {
width: 200px;
}
.test:hover {
opacity: 1;
background: #f00;
transition-duration: 1s, 1s;
transition-delay: 0.25s, 0.25s;
transition-property: background, opacity;
transition-timing-function: ease-in, ease-in;
}
.test:not(:hover) {
opacity: 0.5;
background: #00f;
transition-duration: 2s, 2s;
transition-delay: 0.25s, 0.25s;
transition-property: background, opacity;
transition-timing-function: ease-out, ease-out;
}
ctr('.test', {
width: 200px
hover: {
// applied to both on and non
option: {
ease: 'ease-in'
delay: 0.25s
}
on: {
// option values only applied to on
option: {
duration: 1s
}
opacity: 1
background: red
}
non: {
// option values only applied to non
option: {
duration: 2s
// overrides option
ease: 'ease-out'
}
opacity: 0.5
background: blue
}
}
})
.test {
width: 200px;
}
.test:hover {
opacity: 1;
background: #f00;
transition-duration: 1s, 1s;
transition-delay: 0.25s, 0.25s;
transition-property: background, opacity;
transition-timing-function: ease-in, ease-in;
}
.test:not(:hover) {
opacity: 0.5;
background: #00f;
transition-duration: 2s, 2s;
transition-delay: 0.25s, 0.25s;
transition-property: background, opacity;
transition-timing-function: ease-out, ease-out;
}
.test:
width: 200px
hover:
# applied to both on and non
option:
ease: ease-in
delay: 0.25s
on:
# option values only applied to on
option:
duration: 1s
opacity: 1
background: red
non:
# option values only applied to non
option:
duration: 2s
# overrides option
ease: ease-out
opacity: 0.5
background: blue
Notes
- Option properties and the corresponding
transition
propertiesduration
===transition-duration
delay
===transition-delay
ease
===transition-timing-function
property
===transition-property
- Default option values
duration
===0.5s
delay
===0s
ease
===cubic-bezier(0.42, 0, 0.58, 1)
property
=== If no value is specified properties are auto generated
- You also can specify property-specific options using
shorthand
- it’s bomb-[dot]-com - If you need to, or prefer the
transition
shorthand properties syntax, as intranstion: name | duration | timing-function | ...
, you can do so through thetransitionShorthand
option
Implicit Auxiliary¶
Description: A state
Object absent an auxiliary state such as on
, non
, or static
is an implicit state
. An implicit state
creates a pseudo-class condition for the <identifier>
and transition properties for the enclosed CSS as well as a negation condition absent of the raw CSS for the <identifier>
at the scope level it is defined.
ctr('.test', {
width: 200px
hover: {
opacity: 1
height: 400px
}
})
.test:
width: 200px
hover:
opacity: 1
height: 400px
.test {
width: 200px;
}
.test:hover {
opacity: 1;
height: 400px;
transition-delay: 0s, 0s;
transition-duration: 0.5s, 0.5s;
transition-property: opacity, height;
transition-timing-function: cubic-bezier(0.42, 0, 0.58, 1), cubic-bezier(0.42, 0, 0.58, 1);
}
.test:not(:hover) {
transition-delay: 0s, 0s;
transition-duration: 0.5s, 0.5s;
transition-property: opacity, height;
transition-timing-function: cubic-bezier(0.42, 0, 0.58, 1), cubic-bezier(0.42, 0, 0.58, 1);
}
ctr('.test', {
width: 200px
hover: {
opacity: 1
height: 400px
}
})
.test {
width: 200px;
}
.test:hover {
opacity: 1;
height: 400px;
transition-delay: 0s, 0s;
transition-duration: 0.5s, 0.5s;
transition-property: opacity, height;
transition-timing-function: cubic-bezier(0.42, 0, 0.58, 1), cubic-bezier(0.42, 0, 0.58, 1);
}
.test:not(:hover) {
transition-delay: 0s, 0s;
transition-duration: 0.5s, 0.5s;
transition-property: opacity, height;
transition-timing-function: cubic-bezier(0.42, 0, 0.58, 1), cubic-bezier(0.42, 0, 0.58, 1);
}
.test:
width: 200px
hover:
opacity: 1
height: 400px
Notes
- I always recommend you use the explicit syntax when you can, however, this notation can come handy in various use cases