You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
234 lines
5.5 KiB
234 lines
5.5 KiB
2 years ago
|
# Style DSL
|
||
4 years ago
|
|
||
|
In this tutorial we have a look at how to style the components using the Style DSL. It’s a typesafe DSL for style sheets, which you can use to express CSS rules in your Kotlin code, and even modify styles based on the state of your Compose application.
|
||
|
|
||
|
|
||
|
### Inline Style
|
||
|
|
||
|
You can declare inline styles via the `style` block of a component
|
||
|
|
||
4 years ago
|
``` kotlin
|
||
4 years ago
|
Div({
|
||
|
style {
|
||
4 years ago
|
display(DisplayStyle.Flex)
|
||
|
padding(20.px)
|
||
|
|
||
|
// custom property (or not supported out of a box)
|
||
3 years ago
|
property("font-family", "Arial, Helvetica, sans-serif")
|
||
4 years ago
|
}
|
||
4 years ago
|
}) { /* content goes here */ }
|
||
4 years ago
|
```
|
||
|
|
||
|
In HTML, it will look like this:
|
||
|
|
||
|
```html
|
||
|
<div style="display: flex; padding: 20px; font-family: Arial, Helvetica, sans-serif;"></div>
|
||
|
```
|
||
|
|
||
|
|
||
|
### Stylesheet
|
||
|
An alternative way is to define a Stylesheet that contains rules:
|
||
|
|
||
4 years ago
|
``` kotlin
|
||
4 years ago
|
object AppStylesheet : StyleSheet() {
|
||
|
val container by style { // container is a class
|
||
|
display(DisplayStyle.Flex)
|
||
|
padding(20.px)
|
||
|
|
||
|
// custom property (or not supported out of a box)
|
||
3 years ago
|
property("font-family", "Arial, Helvetica, sans-serif")
|
||
4 years ago
|
}
|
||
|
}
|
||
|
|
||
|
// Stylesheet needs to be mounted:
|
||
|
renderComposable("root") {
|
||
|
Style(AppStylesheet)
|
||
|
|
||
|
Container {
|
||
|
Text("Content")
|
||
|
}
|
||
|
}
|
||
|
|
||
|
@Composable
|
||
|
fun Container(content: @Composable () -> Unit) {
|
||
|
Div(
|
||
|
attrs = { classes(AppStylesheet.container) }
|
||
|
) {
|
||
|
content()
|
||
|
}
|
||
|
}
|
||
|
```
|
||
|
|
||
|
In HTML, it will look like this:
|
||
|
|
||
|
```html
|
||
|
<style></style>
|
||
|
<div class="AppStylesheet-container">Content</div>
|
||
|
```
|
||
|
|
||
|
### Selectors examples
|
||
|
|
||
|
The Style DSL also provides a way to combine and unify selectors:
|
||
|
|
||
4 years ago
|
``` kotlin
|
||
4 years ago
|
object AppStylesheet : StyleSheet() {
|
||
|
|
||
|
init {
|
||
3 years ago
|
// `universal` can be used instead of "*": `universal style {}`
|
||
4 years ago
|
"*" style {
|
||
|
fontSize(15.px)
|
||
|
padding(0.px)
|
||
|
}
|
||
|
|
||
|
// raw selector
|
||
|
"h1, h2, h3, h4, h5, h6" style {
|
||
3 years ago
|
property("font-family", "Arial, Helvetica, sans-serif")
|
||
4 years ago
|
|
||
|
}
|
||
|
|
||
|
// combined selector
|
||
|
type("A") + attr( // selects all tags <a> with href containing 'jetbrains'
|
||
|
name = "href",
|
||
|
value = "jetbrains",
|
||
|
operator = CSSSelector.Attribute.Operator.Equals
|
||
|
) style {
|
||
|
fontSize(25.px)
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// A convenient way to create a class selector
|
||
4 years ago
|
// AppStylesheet.container can be used as a class in component attrs
|
||
4 years ago
|
val container by style {
|
||
3 years ago
|
color(Color.red)
|
||
4 years ago
|
|
||
|
// hover selector for a class
|
||
|
self + hover() style { // self is a selector for `container`
|
||
3 years ago
|
color(Color.green)
|
||
4 years ago
|
}
|
||
|
}
|
||
|
}
|
||
|
```
|
||
|
|
||
|
|
||
|
### Media query example
|
||
|
|
||
|
To specify media queries, you can use the `media` function, which takes the related query, and a block of styles:
|
||
|
|
||
4 years ago
|
``` kotlin
|
||
4 years ago
|
object AppStylesheet : StyleSheet() {
|
||
|
val container by style {
|
||
|
padding(48.px)
|
||
|
|
||
|
media(maxWidth(640.px)) {
|
||
|
self style {
|
||
|
padding(12.px)
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
```
|
||
|
|
||
|
### CSS Variables
|
||
|
|
||
|
The style DSL also provides support for CSS variables.
|
||
|
|
||
4 years ago
|
``` kotlin
|
||
3 years ago
|
object MyVariables {
|
||
4 years ago
|
// declare a variable
|
||
3 years ago
|
val contentBackgroundColor by variable<CSSColorValue>()
|
||
4 years ago
|
}
|
||
|
|
||
|
object MyStyleSheet: StyleSheet() {
|
||
|
|
||
|
val container by style {
|
||
|
//set variable's value for the `container` scope
|
||
|
MyVariables.contentBackgroundColor(Color("blue"))
|
||
|
}
|
||
|
|
||
|
val content by style {
|
||
|
// get the value
|
||
|
backgroundColor(MyVariables.contentBackgroundColor.value())
|
||
|
}
|
||
|
|
||
|
val contentWithDefaultBgColor by style {
|
||
|
// default value can be provided as well
|
||
|
// default value is used when the value is not previously set
|
||
|
backgroundColor(MyVariables.contentBackgroundColor.value(Color("#333")))
|
||
|
}
|
||
|
}
|
||
4 years ago
|
```
|
||
4 years ago
|
|
||
|
|
||
|
### Runnable example
|
||
|
|
||
|
```kotlin
|
||
4 years ago
|
import androidx.compose.runtime.Composable
|
||
|
import org.jetbrains.compose.web.css.*
|
||
|
import org.jetbrains.compose.web.dom.*
|
||
|
import org.jetbrains.compose.web.renderComposable
|
||
4 years ago
|
|
||
3 years ago
|
object MyVariables {
|
||
|
// declare a variable
|
||
|
val contentBackgroundColor by variable<CSSColorValue>()
|
||
|
}
|
||
|
|
||
|
object MyStyleSheet: StyleSheet() {
|
||
|
|
||
|
val container by style {
|
||
|
//set variable's value for the `container` scope
|
||
|
MyVariables.contentBackgroundColor(Color("blue"))
|
||
|
}
|
||
|
|
||
|
val content by style {
|
||
|
// get the value
|
||
|
backgroundColor(MyVariables.contentBackgroundColor.value())
|
||
|
}
|
||
|
|
||
|
val contentWithDefaultBgColor by style {
|
||
|
// default value can be provided as well
|
||
|
// default value is used when the value is not previously set
|
||
|
backgroundColor(MyVariables.contentBackgroundColor.value(Color("#333")))
|
||
|
}
|
||
|
}
|
||
|
|
||
4 years ago
|
object AppStylesheet : StyleSheet() {
|
||
|
val container by style { // container is a class
|
||
|
display(DisplayStyle.Flex)
|
||
|
padding(20.px)
|
||
|
|
||
|
// custom property (or not supported out of a box)
|
||
3 years ago
|
property("font-family", "Arial, Helvetica, sans-serif")
|
||
4 years ago
|
}
|
||
|
}
|
||
|
|
||
|
@Composable
|
||
|
fun Container(content: @Composable () -> Unit) {
|
||
|
Div(
|
||
|
attrs = { classes(AppStylesheet.container) }
|
||
|
) {
|
||
|
content()
|
||
|
}
|
||
|
}
|
||
|
|
||
|
fun main() {
|
||
|
renderComposable(rootElementId = "root") {
|
||
4 years ago
|
Div({
|
||
|
style {
|
||
4 years ago
|
display(DisplayStyle.Flex)
|
||
|
padding(20.px)
|
||
|
|
||
|
// custom property (or not supported out of a box)
|
||
3 years ago
|
property("font-family", "Arial, Helvetica, sans-serif")
|
||
4 years ago
|
}
|
||
4 years ago
|
}) { /* content goes here */ }
|
||
4 years ago
|
|
||
|
|
||
|
Style(AppStylesheet)
|
||
|
|
||
|
Container {
|
||
|
Text("Content")
|
||
|
}
|
||
|
}
|
||
|
}
|
||
3 years ago
|
```
|