swifweb/autolayout
This library gives you the powerful autolayout which works on pure CSS3 ❤️
Breakpoints
Normally we have to declare @media rules in a stylesheet, and it takes a lot of time.
With autolayout you could declare breakpoints (aka @media rules) once and use it as an alias.
There are predefined breakpoints for you:
.xs or .extraSmall // <576px
.s or .small // ≥576px and <768px
.m or .medium // ≥768px and <992px
.l or .large // ≥992px and <1200px
.xl or .extraLarge // ≥1200px and <1400px
.xxl or .extraExtraLarge // ≥1400pxor you can declare your own (just notice how long they are):
extension MediaRule.MediaType {
static var extraSmall: MediaRule.MediaType { .init(.all.maxWidth(575.px), label: "xs") }
static var small: MediaRule.MediaType { .init(.all.minWidth(576.px).maxWidth(767.px), label: "s") }
static var medium: MediaRule.MediaType { .init(.all.minWidth(768.px).maxWidth(991.px), label: "m") }
}use
label: "xs"to prettify your breakpoint in the source code, cause otherwise it will use just the whole rule text
Breakpoints can be added in the end of any autolayout-method. It uses full power of CSS3 @media rule under the hood.
.top(100.px, breakpoints: .extraSmall, .small, .medium)Or you can use breakpoints within the classic stylesheet
@DOM override var body: DOM.Content {
Stylesheet {
Rule(Body.pointer)
.margin(all: 0.px)
.padding(all: 0.px)
MediaRule(.xs, .s) { // will be applied only for extra-small and small screens
Rule(Body.pointer)
.backgroundColor(0x9bc4e2)
}
MediaRule(.m, .l, .xl) { // will be applied only for medium, large, and extra-large screens
Rule(Body.pointer)
.backgroundColor(0xffd700)
}
}
// ...other elements...
}Methods
### Overriding
You can declare different values for the same property but with different breakpoints
```swift
// will be applied in any case
.width(600.px)
// will override any other values when screen width is extra-small or small
.width(200.px, breakpoints: .xs, .s)
// will override any other values when screen width is medium or large
.width(400.px, breakpoints: .m, .l)
```
The library will take care of overriding priority.
### Positioning
`top, right, bottom, left, center, width, height` methods relate to `position` property of the element and of its parent
#### Setting global position
if you want to set these properties globally (to the window boundaries) then use
```swift
.position(.absolute) // or .fixed, .sticky
```
#### Setting relative position
if you want to set these properties relative to its parent then use
```swift
.position(.relative)
```
and don't forget that that's parent also should have
```swift
.position(.relative)
```
or the parent of its parent and so on
#### Potential confusion
Please don't forget that with
```swift
.position(.static) // or if position haven't been set at all
```
only `width` and `height` property works, other properties just can't work in this case
> Each method also can be used with `@State` value
### Top
Specifies `top` position to the first parent element with relative position
#### Top to top
```swift
// will set top to 0px
.top()
// will set top to 100px
.top(100.px)
// will set top to 50px
.top(100.px, multiplier: 0.5)
// will set top to 0px only for extra-small, small and medium screens
.top(breakpoints: .xs, .s, .m)
// will set top to 50px only for extra-small, small and medium screens
.top(50.px, breakpoints: .xs, .s, .m)
// will set top to 25px only for extra-small, small and medium screens
.top(50.px, multiplier: 0.5, breakpoints: .xs, .s, .m)
```
#### Top to center
Simply add `side: .center` as a second argument and `top` side will stick to `center` of the first parent with relative position
```swift
// will set top to 0px from the center
.top(side: .center)
// will set top to 100px from the center
.top(100.px, side: .center)
// will set top to 50px from the center
.top(100.px, side: .center, multiplier: 0.5)
// will set top to 0px from the center only for extra-small, small and medium screens
.top(side: .center, breakpoints: .xs, .s, .m)
// will set top to 50px from the center only for extra-small, small and medium screens
.top(50.px, side: .center, breakpoints: .xs, .s, .m)
// will set top to 25px from the center only for extra-small, small and medium screens
.top(50.px, side: .center, multiplier: 0.5, breakpoints: .xs, .s, .m)
```
#### Top to bottom
Simply add `side: .bottom` as a second argument and `top` side will stick to `bottom` of the first parent with relative position
```swift
// will set top to 0px from the bottom
.top(side: .bottom)
// will set top to 100px from the bottom
.top(100.px, side: .bottom)
// will set top to 50px from the bottom
.top(100.px, side: .bottom, multiplier: 0.5)
// will set top to 0px from the bottom only for extra-small, small and medium screens
.top(side: .bottom, breakpoints: .xs, .s, .m)
// will set top to 50px from the bottom only for extra-small, small and medium screens
.top(50.px, side: .bottom, breakpoints: .xs, .s, .m)
// will set top to 25px from the bottom only for extra-small, small and medium screens
.top(50.px, side: .bottom, multiplier: 0.5, breakpoints: .xs, .s, .m)
```
### Bottom
Specifies `bottom` position to the first parent element with relative position
#### Bottom to bottom
```swift
// will set bottom to 0px
.bottom()
// will set bottom to 100px
.bottom(100.px)
// will set bottom to 50px
.bottom(100.px, multiplier: 0.5)
// will set bottom to 0px only for extra-small, small and medium screens
.bottom(breakpoints: .xs, .s, .m)
// will set bottom to 50px only for extra-small, small and medium screens
.bottom(50.px, breakpoints: .xs, .s, .m)
// will set bottom to 25px only for extra-small, small and medium screens
.bottom(50.px, multiplier: 0.5, breakpoints: .xs, .s, .m)
```
#### Bottom to center
Simply add `side: .center` as a second argument and `bottom` side will stick to `center` of the first parent with relative position
```swift
// will set bottom to 0px from the center
.bottom(side: .center)
// will set bottom to 100px from the center
.bottom(100.px, side: .center)
// will set bottom to 50px from the center
.bottom(100.px, side: .center, multiplier: 0.5)
// will set bottom to 0px from the center only for extra-small, small and medium screens
.bottom(side: .center, breakpoints: .xs, .s, .m)
// will set bottom to 50px from the center only for extra-small, small and medium screens
.bottom(50.px, side: .center, breakpoints: .xs, .s, .m)
// will set bottom to 25px from the center only for extra-small, small and medium screens
.bottom(50.px, side: .center, multiplier: 0.5, breakpoints: .xs, .s, .m)
```
#### Bottom to top
Simply add `side: .top` as a second argument and `bottom` side will stick to `top` of the first parent with relative position
```swift
// will set bottom to 0px from the top
.bottom(side: .top)
// will set bottom to 100px from the top
.bottom(100.px, side: .top)
// will set bottom to 50px from the top
.bottom(100.px, side: .top, multiplier: 0.5)
// will set bottom to 0px from the top only for extra-small, small and medium screens
.bottom(side: .top, breakpoints: .xs, .s, .m)
// will set bottom to 50px from the top only for extra-small, small and medium screens
.bottom(50.px, side: .top, breakpoints: .xs, .s, .m)
// will set bottom to 25px from the top only for extra-small, small and medium screens
.bottom(50.px, side: .top, multiplier: 0.5, breakpoints: .xs, .s, .m)
```
### Left
Specifies `left` position to the first parent element with relative position
#### Left to left
```swift
// will set left to 0px
.left()
// will set left to 100px
.left(100.px)
// will set left to 50px
.left(100.px, multiplier: 0.5)
// will set left to 0px only for extra-small, small and medium screens
.left(breakpoints: .xs, .s, .m)
// will set left to 50px only for extra-small, small and medium screens
.left(50.px, breakpoints: .xs, .s, .m)
// will set left to 25px only for extra-small, small and medium screens
.left(50.px, multiplier: 0.5, breakpoints: .xs, .s, .m)
```
#### Left to center
Simply add `side: .center` as a second argument and `left` side will stick to `center` of the first parent with relative position
```swift
// will set left to 0px from the center
.left(side: .center)
// will set left to 100px from the center
.left(100.px, side: .center)
// will set left to 50px from the center
.left(100.px, side: .center, multiplier: 0.5)
// will set left to 0px from the center only for extra-small, small and medium screens
.left(side: .center, breakpoints: .xs, .s, .m)
// will set left to 50px from the center only for extra-small, small and medium screens
.left(50.px, side: .center, breakpoints: .xs, .s, .m)
// will set left to 25px from the center only for extra-small, small and medium screens
.left(50.px, side: .center, multiplier: 0.5, breakpoints: .xs, .s, .m)
```
#### Left to right
Simply add `side: .right` as a second argument and `left` side will stick to `right` of the first parent with relative position
```swift
// will set left to 0px from the right
.left(side: .right)
// will set left to 100px from the right
.left(100.px, side: .right)
// will set left to 50px from the right
.left(100.px, side: .right, multiplier: 0.5)
// will set left to 0px from the right only for extra-small, small and medium screens
.left(side: .right, breakpoints: .xs, .s, .m)
// will set left to 50px from the right only for extra-small, small and medium screens
.left(50.px, side: .right, breakpoints: .xs, .s, .m)
// will set left to 25px from the right only for extra-small, small and medium screens
.left(50.px, side: .right, multiplier: 0.5, breakpoints: .xs, .s, .m)
```
### Right
Specifies `right` position to the first parent element with relative position
#### Right to right
```swift
// will set right to 0px
.right()
// will set right to 100px
.right(100.px)
// will set right to 50px
.right(100.px, multiplier: 0.5)
// will set right to 0px only for extra-small, small and medium screens
.right(breakpoints: .xs, .s, .m)
// will set right to 50px only for extra-small, small and medium screens
.right(50.px, breakpoints: .xs, .s, .m)
// will set right to 25px only for extra-small, small and medium screens
.right(50.px, multiplier: 0.5, breakpoints: .xs, .s, .m)
```
#### Right to center
Simply add `side: .center` as a second argument and `right` side will stick to `center` of the first parent with relative position
```swift
// will set right to 0px from the center
.right(side: .center)
// will set right to 100px from the center
.right(100.px, side: .center)
// will set right to 50px from the center
.right(100.px, side: .center, multiplier: 0.5)
// will set right to 0px from the center only for extra-small, small and medium screens
.right(side: .center, breakpoints: .xs, .s, .m)
// will set right to 50px from the center only for extra-small, small and medium screens
.right(50.px, side: .center, breakpoints: .xs, .s, .m)
// will set right to 25px from the center only for extra-small, small and medium screens
.right(50.px, side: .center, multiplier: 0.5, breakpoints: .xs, .s, .m)
```
#### Right to left
Simply add `side: .left` as a second argument and `right` side will stick to `left` of the first parent with relative position
```swift
// will set right to 0px from the left
.right(side: .left)
// will set right to 100px from the left
.right(100.px, side: .left)
// will set right to 50px from the left
.right(100.px, side: .left, multiplier: 0.5)
// will set right to 0px from the left only for extra-small, small and medium screens
.right(side: .left, breakpoints: .xs, .s, .m)
// will set right to 50px from the left only for extra-small, small and medium screens
.right(50.px, side: .left, breakpoints: .xs, .s, .m)
// will set right to 25px from the left only for extra-small, small and medium screens
.right(50.px, side: .left, multiplier: 0.5, breakpoints: .xs, .s, .m)
```
### Edges
Convenience setter for all sides: top, right, bottom, left
#### All edges
```swift
// Will set top, right, bottom, and left to 0px
.edges()
// Will set top, right, bottom, and left to 10px
.edges(10.px)
// Will set top, right, bottom, and left to 5px only for extra-small, small and medium screens
.edges(5.px, breakpoints: .xs, .s, .m)
```
#### Horizontal edges
```swift
// Will set left and right to 0px
.edges(h: 0.px)
// Will set left and right to 10px
.edges(h: 10.px)
// Will set left and right to 5px only for extra-small, small and medium screens
.edges(h: 5.px, breakpoints: .xs, .s, .m)
```
#### Vertical edges
```swift
// Will set top and bottom to 0px
.edges(v: 0.px)
// Will set top and bottom to 10px
.edges(v: 10.px)
// Will set top and bottom to 5px only for extra-small, small and medium screens
.edges(v: 5.px, breakpoints: .xs, .s, .m)
```
#### Horizontal and vertical edges
```swift
// Will set left and right to 0px, and top and bottom to 0px
.edges(h: 0.px, v: 0.px)
// Will set left and right to 0px, and top and bottom to 10px
.edges(h: 0.px, v: 10.px)
// Will set left and right to 2px, and top and bottom to 4px only for extra-small, small and medium screens
.edges(h: 2.px, v: 4.px, breakpoints: .xs, .s, .m)
```
### Center X
Specifies the horizontal center position to the first parent element with relative position
#### Center to center
```swift
// will set centerX to 0px
.centerX()
// will set centerX to 100px
.centerX(100.px)
// will set centerX to 50px
.centerX(100.px, multiplier: 0.5)
// will set centerX to 0px only for extra-small, small and medium screens
.centerX(breakpoints: .xs, .s, .m)
// will set centerX to 50px only for extra-small, small and medium screens
.centerX(50.px, breakpoints: .xs, .s, .m)
// will set centerX to 25px only for extra-small, small and medium screens
.centerX(50.px, multiplier: 0.5, breakpoints: .xs, .s, .m)
```
#### Center to left
Simply add `side: .left` as a second argument and `centerX` side will stick to `left` of the first parent with relative position
```swift
// will set centerX to 0px of the left
.centerX(side: .left)
// will set centerX to 100px of the left
.centerX(100.px, side: .left)
// will set centerX to 50px of the left
.centerX(100.px, side: .left, multiplier: 0.5)
// will set centerX to 0px of the left only for extra-small, small and medium screens
.centerX(side: .left, breakpoints: .xs, .s, .m)
// will set centerX to 50px of the left only for extra-small, small and medium screens
.centerX(50.px, side: .left, breakpoints: .xs, .s, .m)
// will set centerX to 25px of the left only for extra-small, small and medium screens
.centerX(50.px, side: .left, multiplier: 0.5, breakpoints: .xs, .s, .m)
```
#### Center to right
Simply add `side: .right` as a second argument and `centerX ` side will stick to `right` of the first parent with relative position
```swift
// will set centerX to 0px of the right
.centerX(side: .right)
// will set centerX to 100px of the right
.centerX(100.px, side: .right)
// will set centerX to 50px of the right
.centerX(100.px, side: .right, multiplier: 0.5)
// will set centerX to 0px of the right only for extra-small, small and medium screens
.centerX(side: .right, breakpoints: .xs, .s, .m)
// will set centerX to 50px of the right only for extra-small, small and medium screens
.centerX(50.px, side: .right, breakpoints: .xs, .s, .m)
// will set centerX to 25px of the right only for extra-small, small and medium screens
.centerX(50.px, side: .right, multiplier: 0.5, breakpoints: .xs, .s, .m)
```
### Center Y
Specifies the vertical center position to the first parent element with relative position
#### Center to center
```swift
// will set centerY to 0px
.centerY()
// will set centerY to 100px
.centerY(100.px)
// will set centerY to 50px
.centerY(100.px, multiplier: 0.5)
// will set centerY to 0px only for extra-small, small and medium screens
.centerY(breakpoints: .xs, .s, .m)
// will set centerY to 50px only for extra-small, small and medium screens
.centerY(50.px, breakpoints: .xs, .s, .m)
// will set centerY to 25px only for extra-small, small and medium screens
.centerY(50.px, multiplier: 0.5, breakpoints: .xs, .s, .m)
```
#### Center to top
Simply add `side: .top` as a second argument and `centerY` side will stick to `top` of the first parent with relative position
```swift
// will set centerY to 0px of the top
.centerY(side: .top)
// will set centerY to 100px of the top
.centerY(100.px, side: .top)
// will set centerY to 50px of the top
.centerY(100.px, side: .top, multiplier: 0.5)
// will set centerY to 0px of the top only for extra-small, small and medium screens
.centerY(side: .top, breakpoints: .xs, .s, .m)
// will set centerY to 50px of the top only for extra-small, small and medium screens
.centerY(50.px, side: .top, breakpoints: .xs, .s, .m)
// will set centerY to 25px of the top only for extra-small, small and medium screens
.centerY(50.px, side: .top, multiplier: 0.5, breakpoints: .xs, .s, .m)
```
#### Center to bottom
Simply add `side: .bottom` as a second argument and `centerY ` side will stick to `bottom` of the first parent with relative position
```swift
// will set centerY to 0px of the bottom
.centerY(side: .bottom)
// will set centerY to 100px of the bottom
.centerY(100.px, side: .bottom)
// will set centerY to 50px of the bottom
.centerY(100.px, side: .bottom, multiplier: 0.5)
// will set centerY to 0px of the bottom only for extra-small, small and medium screens
.centerY(side: .bottom, breakpoints: .xs, .s, .m)
// will set centerY to 50px of the bottom only for extra-small, small and medium screens
.centerY(50.px, side: .bottom, breakpoints: .xs, .s, .m)
// will set centerY to 25px of the bottom only for extra-small, small and medium screens
.centerY(50.px, side: .bottom, multiplier: 0.5, breakpoints: .xs, .s, .m)
```
### Center X+Y
Specifies both vertical and horizontal center position to the first parent element with relative position
```swift
// will set centerX and centerY to 0px
.center()
// will set centerX and centerY to 100px
.center(100.px)
// will set centerX and centerY to 50px
.center(100.px, multiplier: 0.5)
// will set centerX and centerY to 0px only for extra-small, small and medium screens
.center(breakpoints: .xs, .s, .m)
// will set centerX and centerY to 50px only for extra-small, small and medium screens
.center(50.px, breakpoints: .xs, .s, .m)
// will set centerX and centerY to 25px only for extra-small, small and medium screens
.center(50.px, multiplier: 0.5, breakpoints: .xs, .s, .m)
```
### Width
Sets width of an element
```swift
// will set width to 0px
.width()
// will set width to 100px
.width(100.px)
// will set width to 100%
.width(100.percent)
// will set width to 50px
.width(100.px, multiplier: 0.5)
// will set width to 0px only for extra-small, small and medium screens
.width(breakpoints: .xs, .s, .m)
// will set width to 50px only for extra-small, small and medium screens
.width(50.px, breakpoints: .xs, .s, .m)
// will set width to 25px only for extra-small, small and medium screens
.width(50.px, multiplier: 0.5, breakpoints: .xs, .s, .m)
```
### Width to parent
Sets width of an element to fit first parent element with relative position
```swift
// will set width to 100% of first parent element with relative position
.widthToParent()
// will set width to 100% of first parent element with relative position only for extra-small, small and medium screens
.widthToParent(breakpoints: .xs, .s, .m)
// will set width to 100% + 100px of first parent element with relative position
.widthToParent(extra: 100.px)
// will set width to 100% + 100px of first parent element with relative position
// only for extra-small, small and medium screens
.widthToParent(extra: 100.px, breakpoints: .xs, .s, .m)
// will set width to (100% + 100px) * 0.5 of first parent element with relative position
.widthToParent(extra: 100.px, multiplier: 0.5)
// will set width to (100% + 100px) * 0.5 of first parent element with relative position
// only for extra-small, small and medium screens
.widthToParent(extra: 100.px, multiplier: 0.5, breakpoints: .xs, .s, .m)
// will set width to 50% of first parent element with relative position
.widthToParent(multiplier: 0.5)
// will set width to 50% of first parent element with relative position
// only for extra-small, small and medium screens
.widthToParent(multiplier: 0.5, breakpoints: .xs, .s, .m)
```
### Height
Sets height of an element
```swift
// will set height to 0px
.height()
// will set height to 100px
.height(100.px)
// will set height to 100%
.height(100.percent)
// will set height to 50px
.height(100.px, multiplier: 0.5)
// will set height to 0px only for extra-small, small and medium screens
.height(breakpoints: .xs, .s, .m)
// will set height to 50px only for extra-small, small and medium screens
.height(50.px, breakpoints: .xs, .s, .m)
// will set height to 25px only for extra-small, small and medium screens
.height(50.px, multiplier: 0.5, breakpoints: .xs, .s, .m)
```
### Height to parent
Sets height of an element to fit first parent element with relative position
```swift
// will set height to 100% of first parent element with relative position
.heightToParent()
// will set height to 100% of first parent element with relative position only for extra-small, small and medium screens
.heightToParent(breakpoints: .xs, .s, .m)
// will set height to 100% + 100px of first parent element with relative position
.heightToParent(extra: 100.px)
// will set height to 100% + 100px of first parent element with relative position
// only for extra-small, small and medium screens
.heightToParent(extra: 100.px, breakpoints: .xs, .s, .m)
// will set height to (100% + 100px) * 0.5 of first parent element with relative position
.heightToParent(extra: 100.px, multiplier: 0.5)
// will set height to (100% + 100px) * 0.5 of first parent element with relative position
// only for extra-small, small and medium screens
.heightToParent(extra: 100.px, multiplier: 0.5, breakpoints: .xs, .s, .m)
// will set height to 50% of first parent element with relative position
.heightToParent(multiplier: 0.5)
// will set height to 50% of first parent element with relative position
// only for extra-small, small and medium screens
.heightToParent(multiplier: 0.5, breakpoints: .xs, .s, .m)
```
### Position
Specifies the type of positioning method used for an element `static, relative, absolute or fixed`
```swift
// will set position to absolute
.position(.absolute)
// will set position to absolute only for extra-small, small and medium screens
.position(.absolute, breakpoints: .xs, .s, .m)
```
### Display
Specifies how a certain HTML element should be displayed
```swift
// will set display to block
.display(.block)
// will set display to block only for extra-small, small and medium screens
.display(.block, breakpoints: .xs, .s, .m)
```
### Visibility
Specifies whether or not an element is visible
```swift
// will set visibility to visible
.visibility(.visible)
// will set visibility to hidden only for extra-small, small and medium screens
.visibility(.hidden, breakpoints: .xs, .s, .m)
```
### Opacity
Sets the opacity level for an element
```swift
// will set opacity to 0.8
.opacity(0.8)
// will set opacity to 0.5 only for extra-small, small and medium screens
.opacity(0.5, breakpoints: .xs, .s, .m)
```
# Live preview
To make it work with live preview you need to specify either all styles or exact autolayout's one
#### With all app styles included
```swift
class Welcome_Preview: WebPreview {
override class var title: String { "Initial page" } // optional
override class var width: UInt { 440 } // optional
override class var height: UInt { 480 } // optional
@Preview override class var content: Preview.Content {
// add styles if needed
AppStyles.all
// add here as many elements as needed
WelcomeViewController()
}
}
```
#### With exact app styles including autoalyout's one
```swift
class Welcome_Preview: WebPreview {
override class var title: String { "Initial page" } // optional
override class var width: UInt { 440 } // optional
override class var height: UInt { 480 } // optional
@Preview override class var content: Preview.Content {
// add styles if needed
AppStyles.id(.mainStyle)
AppStyles.id(.autolayoutStyles)
// add here as many elements as needed
WelcomeViewController()
}
}
```Package Metadata
Repository: swifweb/autolayout
Default branch: master
README: README.md