From 769c8d824600fbf521e3976cc4a3c6152ed4e8ce Mon Sep 17 00:00:00 2001 From: Martijn Cuppens Date: Thu, 23 May 2019 11:56:03 +0200 Subject: [PATCH] Helpers & utilities split (#28445) --- package.json | 4 +- scss/_functions.scss | 24 + scss/_helpers.scss | 7 + scss/_mixins.scss | 5 +- scss/_utilities.scss | 460 +++++++++++++++++- scss/_variables.scss | 30 +- scss/bootstrap-grid.scss | 47 +- scss/bootstrap.scss | 21 +- scss/helpers/_background.scss | 5 + scss/{utilities => helpers}/_clearfix.scss | 0 scss/{utilities => helpers}/_embed.scss | 0 scss/{utilities => helpers}/_position.scss | 5 - .../_screenreaders.scss | 0 .../_stretched-link.scss | 0 scss/helpers/_text.scss | 7 + scss/mixins/_grid-framework.scss | 8 - scss/mixins/_utilities.scss | 33 ++ scss/utilities/_align.scss | 8 - scss/utilities/_api.scss | 29 ++ scss/utilities/_background.scss | 21 - scss/utilities/_borders.scss | 75 --- scss/utilities/_display.scss | 17 - scss/utilities/_flex.scss | 51 -- scss/utilities/_float.scss | 11 - scss/utilities/_overflow.scss | 5 - scss/utilities/_shadows.scss | 6 - scss/utilities/_sizing.scss | 8 - scss/utilities/_spacing.scss | 73 --- scss/utilities/_text.scss | 61 --- .../4.3/{utilities => helpers}/clearfix.md | 3 +- .../docs/4.3/{utilities => helpers}/embed.md | 2 +- site/content/docs/4.3/helpers/position.md | 33 ++ .../{utilities => helpers}/screen-readers.md | 2 +- .../{utilities => helpers}/stretched-link.md | 2 +- site/content/docs/4.3/helpers/text.md | 25 + site/content/docs/4.3/utilities/api.md | 261 ++++++++++ site/content/docs/4.3/utilities/borders.md | 1 - site/content/docs/4.3/utilities/position.md | 26 - site/content/docs/4.3/utilities/text.md | 16 - site/data/nav.yml | 14 +- 40 files changed, 957 insertions(+), 449 deletions(-) create mode 100644 scss/_helpers.scss create mode 100644 scss/helpers/_background.scss rename scss/{utilities => helpers}/_clearfix.scss (100%) rename scss/{utilities => helpers}/_embed.scss (100%) rename scss/{utilities => helpers}/_position.scss (76%) rename scss/{utilities => helpers}/_screenreaders.scss (100%) rename scss/{utilities => helpers}/_stretched-link.scss (100%) create mode 100644 scss/helpers/_text.scss create mode 100644 scss/mixins/_utilities.scss delete mode 100644 scss/utilities/_align.scss create mode 100644 scss/utilities/_api.scss delete mode 100644 scss/utilities/_background.scss delete mode 100644 scss/utilities/_borders.scss delete mode 100644 scss/utilities/_display.scss delete mode 100644 scss/utilities/_flex.scss delete mode 100644 scss/utilities/_float.scss delete mode 100644 scss/utilities/_overflow.scss delete mode 100644 scss/utilities/_shadows.scss delete mode 100644 scss/utilities/_spacing.scss rename site/content/docs/4.3/{utilities => helpers}/clearfix.md (95%) rename site/content/docs/4.3/{utilities => helpers}/embed.md (99%) create mode 100644 site/content/docs/4.3/helpers/position.md rename site/content/docs/4.3/{utilities => helpers}/screen-readers.md (97%) rename site/content/docs/4.3/{utilities => helpers}/stretched-link.md (99%) create mode 100644 site/content/docs/4.3/helpers/text.md create mode 100644 site/content/docs/4.3/utilities/api.md diff --git a/package.json b/package.json index 8a8512b13f..5d9d072a80 100644 --- a/package.json +++ b/package.json @@ -165,11 +165,11 @@ "bundlesize": [ { "path": "./dist/css/bootstrap-grid.css", - "maxSize": "7 kB" + "maxSize": "8 kB" }, { "path": "./dist/css/bootstrap-grid.min.css", - "maxSize": "6 kB" + "maxSize": "7.2 kB" }, { "path": "./dist/css/bootstrap-reboot.css", diff --git a/scss/_functions.scss b/scss/_functions.scss index e867b55211..096b15205f 100644 --- a/scss/_functions.scss +++ b/scss/_functions.scss @@ -30,6 +30,30 @@ } } +// Internal Bootstrap function to turn maps into its negative variant. +// If prefixes the keys with `n` and makes the value negative. +@function negativify-map($map) { + $result: (); + @each $key, $value in $map { + @if $key != 0 { + $result: map-merge($result, ("n" + $key: (-$value))); + } + } + @return $result; +} + +// Get multiple keys from a sass map +@function map-get-multiple($map, $values) { + $result: (); + @each $key, $value in $map { + @if (index($values, $key) != null) { + $result: map-merge($result, ($key: $value)); + } + } + @return $map; +} + + // Replace `$search` with `$replace` in `$string` // Used on our SVG icon backgrounds for custom forms. // diff --git a/scss/_helpers.scss b/scss/_helpers.scss new file mode 100644 index 0000000000..ca57c9babb --- /dev/null +++ b/scss/_helpers.scss @@ -0,0 +1,7 @@ +@import "helpers/background"; +@import "helpers/clearfix"; +@import "helpers/embed"; +@import "helpers/position"; +@import "helpers/screenreaders"; +@import "helpers/stretched-link"; +@import "helpers/text"; diff --git a/scss/_mixins.scss b/scss/_mixins.scss index a8be120638..ffee78ac2e 100644 --- a/scss/_mixins.scss +++ b/scss/_mixins.scss @@ -8,7 +8,7 @@ // Deprecate @import "mixins/deprecate"; -// Utilities +// Helpers @import "mixins/breakpoints"; @import "mixins/image"; @import "mixins/resize"; @@ -17,6 +17,9 @@ @import "mixins/text-emphasis"; @import "mixins/text-truncate"; +// Utilities +@import "mixins/utilities"; + // Components @import "mixins/alert"; @import "mixins/buttons"; diff --git a/scss/_utilities.scss b/scss/_utilities.scss index a5de31ba6a..fec2051009 100644 --- a/scss/_utilities.scss +++ b/scss/_utilities.scss @@ -1,17 +1,443 @@ -@import "utilities/align"; -@import "utilities/background"; -@import "utilities/borders"; -@import "utilities/clearfix"; -@import "utilities/display"; -@import "utilities/embed"; -@import "utilities/flex"; -@import "utilities/float"; -@import "utilities/overflow"; -@import "utilities/position"; -@import "utilities/screenreaders"; -@import "utilities/shadows"; -@import "utilities/sizing"; -@import "utilities/stretched-link"; -@import "utilities/spacing"; -@import "utilities/text"; -@import "utilities/visibility"; +// Utilities + +$utilities: () !default; +// stylelint-disable-next-line scss/dollar-variable-default +$utilities: map-merge( + ( + "align": ( + property: vertical-align, + class: align, + values: baseline top middle bottom text-bottom text-top + ), + "float": ( + responsive: true, + property: float, + values: left right none + ), + "overflow": ( + property: overflow, + values: auto hidden, + ), + "display": ( + responsive: true, + print: true, + property: display, + class: d, + values: none inline inline-block block table table-row table-cell flex inline-flex + ), + "shadow": ( + property: box-shadow, + class: shadow, + values: ( + sm: $box-shadow-sm, + null: $box-shadow, + lg: $box-shadow-lg, + none: none, + ) + ), + "position": ( + property: position, + values: static relative absolute fixed sticky + ), + "border": ( + property: border, + values: ( + null: $border-width solid $border-color, + 0: 0, + ) + ), + "border-top": ( + property: border-top, + values: ( + null: $border-width solid $border-color, + 0: 0, + ) + ), + "border-right": ( + property: border-right, + values: ( + null: $border-width solid $border-color, + 0: 0, + ) + ), + "border-bottom": ( + property: border-bottom, + values: ( + null: $border-width solid $border-color, + 0: 0, + ) + ), + "border-left": ( + property: border-left, + values: ( + null: $border-width solid $border-color, + 0: 0, + ) + ), + "border-color": ( + property: border-color, + class: border, + values: map-merge($theme-colors, (white: $white)) + ), + // Sizing utilities + "width": ( + property: width, + class: w, + values: ( + 25: 25%, + 50: 50%, + 75: 75%, + 100: 100%, + auto: auto + ) + ), + "height": ( + property: height, + class: h, + values: ( + 25: 25%, + 50: 50%, + 75: 75%, + 100: 100%, + auto: auto + ) + ), + // Flex utilities + "flex": ( + responsive: true, + property: flex, + values: (fill: 1 1 auto) + ), + "flex-direction": ( + responsive: true, + property: flex-direction, + class: flex, + values: row column row-reverse column-reverse + ), + "flex-grow": ( + responsive: true, + property: flex-grow, + class: flex, + values: ( + grow-0: 0, + grow-1: 1, + ) + ), + "flex-shrink": ( + responsive: true, + property: flex-shrink, + class: flex, + values: ( + shrink-0: 0, + shrink-1: 1, + ) + ), + "flex-wrap": ( + responsive: true, + property: flex-wrap, + class: flex, + values: wrap nowrap wrap-reverse + ), + "justify-content": ( + responsive: true, + property: justify-content, + values: ( + start: flex-start, + end: flex-end, + center: center, + between: space-between, + around: space-around, + ) + ), + "align-items": ( + responsive: true, + property: align-items, + values: ( + start: flex-start, + end: flex-end, + center: center, + baseline: baseline, + stretch: stretch, + ) + ), + "align-content": ( + responsive: true, + property: align-content, + values: ( + start: flex-start, + end: flex-end, + center: center, + between: space-between, + around: space-around, + stretch: stretch, + ) + ), + "align-self": ( + responsive: true, + property: align-self, + values: ( + auto: auto, + start: flex-start, + end: flex-end, + center: center, + baseline: baseline, + stretch: stretch, + ) + ), + "order": ( + responsive: true, + property: order, + values: ( + first: -1, + 0: 0, + 1: 1, + 2: 2, + 3: 3, + 4: 4, + 5: 5, + 6: 6, + 7: 7, + 8: 8, + 9: 9, + 10: 10, + 11: 11, + 12: 12, + last: 13, + ), + ), + // Margin utilities + "margin": ( + responsive: true, + property: margin, + class: m, + values: map-merge($spacers, (auto: auto)) + ), + "margin-x": ( + responsive: true, + property: margin-right margin-left, + class: mx, + values: map-merge($spacers, (auto: auto)) + ), + "margin-y": ( + responsive: true, + property: margin-top margin-bottom, + class: my, + values: map-merge($spacers, (auto: auto)) + ), + "margin-top": ( + responsive: true, + property: margin-top, + class: mt, + values: map-merge($spacers, (auto: auto)) + ), + "margin-right": ( + responsive: true, + property: margin-right, + class: mr, + values: map-merge($spacers, (auto: auto)) + ), + "margin-bottom": ( + responsive: true, + property: margin-bottom, + class: mb, + values: map-merge($spacers, (auto: auto)) + ), + "margin-left": ( + responsive: true, + property: margin-left, + class: ml, + values: map-merge($spacers, (auto: auto)) + ), + // Negative margin utilities + "negative-margin": ( + responsive: true, + property: margin, + class: m, + values: $negative-spacers + ), + "negative-margin-x": ( + responsive: true, + property: margin-right margin-left, + class: mx, + values: $negative-spacers + ), + "negative-margin-y": ( + responsive: true, + property: margin-top margin-bottom, + class: my, + values: $negative-spacers + ), + "negative-margin-top": ( + responsive: true, + property: margin-top, + class: mt, + values: $negative-spacers + ), + "negative-margin-right": ( + responsive: true, + property: margin-right, + class: mr, + values: $negative-spacers + ), + "negative-margin-bottom": ( + responsive: true, + property: margin-bottom, + class: mb, + values: $negative-spacers + ), + "negative-margin-left": ( + responsive: true, + property: margin-left, + class: ml, + values: $negative-spacers + ), + // Padding utilities + "padding": ( + responsive: true, + property: padding, + class: p, + values: $spacers + ), + "padding-x": ( + responsive: true, + property: padding-right padding-left, + class: px, + values: $spacers + ), + "padding-y": ( + responsive: true, + property: padding-top padding-bottom, + class: py, + values: $spacers + ), + "padding-top": ( + responsive: true, + property: padding-top, + class: pt, + values: $spacers + ), + "padding-right": ( + responsive: true, + property: padding-right, + class: pr, + values: $spacers + ), + "padding-bottom": ( + responsive: true, + property: padding-bottom, + class: pb, + values: $spacers + ), + "padding-left": ( + responsive: true, + property: padding-left, + class: pl, + values: $spacers + ), + // Text + "font-weight": ( + property: font-weight, + values: ( + light: $font-weight-light, + lighter: $font-weight-lighter, + normal: $font-weight-normal, + bold: $font-weight-bold, + bolder: $font-weight-bolder + ) + ), + "text-transform": ( + property: text-transform, + class: text, + values: lowercase uppercase capitalize + ), + "text-align": ( + responsive: true, + property: text-align, + class: text, + values: left right center justify + ), + "color": ( + property: color, + class: text, + values: ( + white: $white, + body: $body-color, + muted: $text-muted, + black-50: rgba($black, .5), + white-50: rgba($white, .5), + reset: inherit, + ) + ), + "background-color": ( + property: background-color, + class: bg, + values: map-merge( + $theme-colors, + ( + white: $white, + transparent: transparent + ) + ) + ), + "white-space": ( + property: white-space, + class: text, + values: ( + wrap: normal, + nowrap: nowrap, + ) + ), + "text-decoration": ( + property: text-decoration, + values: none + ), + "font-style": ( + property: font-style, + class: font, + values: italic + ), + "overflow-wrap": ( + property: overflow-wrap word-break, // word-break for IE & < Edge 18 + class: text, + values: (break: break-word) + ), + "font-family": ( + property: font-family, + class: text, + values: (monospace: $font-family-monospace) + ), + "rounded": ( + property: border-radius, + class: rounded, + values: ( + null: $border-radius, + sm: $border-radius-sm, + lg: $border-radius-lg, + circle: 50%, + pill: $rounded-pill, + 0: 0, + ) + ), + "rounded-top": ( + property: border-top-left-radius border-top-right-radius, + class: rounded-top, + values: (null: $border-radius) + ), + "rounded-right": ( + property: border-top-right-radius border-bottom-right-radius, + class: rounded-right, + values: (null: $border-radius) + ), + "rounded-bottom": ( + property: border-bottom-right-radius border-bottom-left-radius, + class: rounded-bottom, + values: (null: $border-radius) + ), + "rounded-left": ( + property: border-bottom-left-radius border-top-left-radius, + class: rounded-left, + values: (null: $border-radius) + ), + ), + $utilities +); diff --git a/scss/_variables.scss b/scss/_variables.scss index 45b1f1dcab..b3268c1e9e 100644 --- a/scss/_variables.scss +++ b/scss/_variables.scss @@ -131,29 +131,16 @@ $spacers: () !default; $spacers: map-merge( ( 0: 0, - 1: ($spacer * .25), - 2: ($spacer * .5), + 1: $spacer * .25, + 2: $spacer * .5, 3: $spacer, - 4: ($spacer * 1.5), - 5: ($spacer * 3) + 4: $spacer * 1.5, + 5: $spacer * 3, ), $spacers ); -// This variable affects the `.h-*` and `.w-*` classes. -$sizes: () !default; -// stylelint-disable-next-line scss/dollar-variable-default -$sizes: map-merge( - ( - 25: 25%, - 50: 50%, - 75: 75%, - 100: 100%, - auto: auto - ), - $sizes -); - +$negative-spacers: negativify-map($spacers) !default; // Body // @@ -1118,10 +1105,3 @@ $kbd-bg: $gray-900 !default; $pre-color: $gray-900 !default; $pre-scrollable-max-height: 340px !default; - - -// Utilities - -$displays: none, inline, inline-block, block, table, table-row, table-cell, flex, inline-flex !default; -$overflows: auto, hidden !default; -$positions: static, relative, absolute, fixed, sticky !default; diff --git a/scss/bootstrap-grid.scss b/scss/bootstrap-grid.scss index 7772e9f68e..619aa1e83e 100644 --- a/scss/bootstrap-grid.scss +++ b/scss/bootstrap-grid.scss @@ -21,8 +21,49 @@ html { @import "mixins/breakpoints"; @import "mixins/grid-framework"; @import "mixins/grid"; +@import "mixins/utilities"; @import "grid"; -@import "utilities/display"; -@import "utilities/flex"; -@import "utilities/spacing"; + +@import "utilities"; +// Only use the utilities we need +// stylelint-disable-next-line scss/dollar-variable-default +$utilities: map-get-multiple( + $utilities, + ( + "display", + "order", + "flex", + "flex-direction", + "flex-grow", + "flex-shrink" + "flex-wrap", + "justify-content", + "align-items", + "align-content", + "align-self", + "margin", + "margin-x", + "margin-y", + "margin-top", + "margin-right", + "margin-bottom", + "margin-left", + "negative-margin", + "negative-margin-x", + "negative-margin-y", + "negative-margin-top", + "negative-margin-right", + "negative-margin-bottom", + "negative-margin-left", + "padding", + "padding-x", + "padding-y", + "padding-top", + "padding-right", + "padding-bottom", + "padding-left", + ) +); + +@import "utilities/api"; diff --git a/scss/bootstrap.scss b/scss/bootstrap.scss index 5ba0ac151b..5f100326b7 100644 --- a/scss/bootstrap.scss +++ b/scss/bootstrap.scss @@ -5,9 +5,16 @@ * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) */ +// Configuration + @import "functions"; @import "variables"; @import "mixins"; +@import "utilities"; + + +// Layout & components + @import "root"; @import "reboot"; @import "type"; @@ -39,4 +46,16 @@ @import "popover"; @import "carousel"; @import "spinners"; -@import "utilities"; + + +// Helpers + +@import "helpers"; + + +// Utilities + +@import "utilities/api"; +@import "utilities/sizing"; +@import "utilities/text"; +@import "utilities/visibility"; diff --git a/scss/helpers/_background.scss b/scss/helpers/_background.scss new file mode 100644 index 0000000000..1c0a32a239 --- /dev/null +++ b/scss/helpers/_background.scss @@ -0,0 +1,5 @@ +@if $enable-gradients { + @each $color, $value in $theme-colors { + @include bg-gradient-variant(".bg-gradient-#{$color}", $value); + } +} diff --git a/scss/utilities/_clearfix.scss b/scss/helpers/_clearfix.scss similarity index 100% rename from scss/utilities/_clearfix.scss rename to scss/helpers/_clearfix.scss diff --git a/scss/utilities/_embed.scss b/scss/helpers/_embed.scss similarity index 100% rename from scss/utilities/_embed.scss rename to scss/helpers/_embed.scss diff --git a/scss/utilities/_position.scss b/scss/helpers/_position.scss similarity index 76% rename from scss/utilities/_position.scss rename to scss/helpers/_position.scss index cdf6c115f3..e0c4c2c110 100644 --- a/scss/utilities/_position.scss +++ b/scss/helpers/_position.scss @@ -1,10 +1,5 @@ // stylelint-disable declaration-no-important -// Common values -@each $position in $positions { - .position-#{$position} { position: $position !important; } -} - // Shorthand .fixed-top { diff --git a/scss/utilities/_screenreaders.scss b/scss/helpers/_screenreaders.scss similarity index 100% rename from scss/utilities/_screenreaders.scss rename to scss/helpers/_screenreaders.scss diff --git a/scss/utilities/_stretched-link.scss b/scss/helpers/_stretched-link.scss similarity index 100% rename from scss/utilities/_stretched-link.scss rename to scss/helpers/_stretched-link.scss diff --git a/scss/helpers/_text.scss b/scss/helpers/_text.scss new file mode 100644 index 0000000000..419703f1ce --- /dev/null +++ b/scss/helpers/_text.scss @@ -0,0 +1,7 @@ +// +// Text +// + +.text-truncate { + @include text-truncate; +} diff --git a/scss/mixins/_grid-framework.scss b/scss/mixins/_grid-framework.scss index 649c28bf77..9aeafc06ea 100644 --- a/scss/mixins/_grid-framework.scss +++ b/scss/mixins/_grid-framework.scss @@ -45,14 +45,6 @@ } } - .order#{$infix}-first { order: -1; } - - .order#{$infix}-last { order: $columns + 1; } - - @for $i from 0 through $columns { - .order#{$infix}-#{$i} { order: $i; } - } - // `$columns - 1` because offsetting by the width of an entire row isn't possible @for $i from 0 through ($columns - 1) { @if not ($infix == "" and $i == 0) { // Avoid emitting useless .offset-0 diff --git a/scss/mixins/_utilities.scss b/scss/mixins/_utilities.scss new file mode 100644 index 0000000000..fb0b2cf406 --- /dev/null +++ b/scss/mixins/_utilities.scss @@ -0,0 +1,33 @@ +// Utility generator +// Used to generate utilities & print utilities +@mixin generate-utility($utility, $infix) { + $values: map-get($utility, values); + + // If the values are a list or string, convert it into a map + @if type-of($values) == "string" or type-of(nth($values, 1)) != "list" { + $values: zip($values, $values); + } + + @each $value in $values { + $properties: map-get($utility, property); + + // Multiple properties are possible, for example with vertical or horizontal margins or paddings + @if type-of($properties) == "string" { + $properties: append((), $properties); + } + + // Use custom class if present + $property-class: map-get($utility, class); + $property-class: if($property-class, $property-class, nth($properties, 1)); + + // Don't prefix if value key is null (eg. with shadow class) + $property-class-modifier: if(nth($value, 1), "-" + nth($value, 1), ""); + + .#{$property-class + $infix + $property-class-modifier} { + @each $property in $properties { + // stylelint-disable-next-line declaration-no-important + #{$property}: #{nth($value, 2)} !important; + } + } + } +} diff --git a/scss/utilities/_align.scss b/scss/utilities/_align.scss deleted file mode 100644 index 8b7df9f76c..0000000000 --- a/scss/utilities/_align.scss +++ /dev/null @@ -1,8 +0,0 @@ -// stylelint-disable declaration-no-important - -.align-baseline { vertical-align: baseline !important; } // Browser default -.align-top { vertical-align: top !important; } -.align-middle { vertical-align: middle !important; } -.align-bottom { vertical-align: bottom !important; } -.align-text-bottom { vertical-align: text-bottom !important; } -.align-text-top { vertical-align: text-top !important; } diff --git a/scss/utilities/_api.scss b/scss/utilities/_api.scss new file mode 100644 index 0000000000..5b9b6651cb --- /dev/null +++ b/scss/utilities/_api.scss @@ -0,0 +1,29 @@ +// Loop over each breakpoint +@each $breakpoint in map-keys($grid-breakpoints) { + + // Generate media query if needed + @include media-breakpoint-up($breakpoint) { + $infix: breakpoint-infix($breakpoint, $grid-breakpoints); + + // Loop over each utility property + @each $key, $utility in $utilities { + // The utility can be disabled with `false`, thus check if the utility is a map first + // Only proceed if responsive media queries are enabled or if it's the base media query + @if type-of($utility) == "map" and (map-get($utility, responsive) or $infix == "") { + @include generate-utility($utility, $infix); + } + } + } +} + + +// Print utilities +@media print { + @each $key, $utility in $utilities { + // The utility can be disabled with `false`, thus check if the utility is a map first + // Then check if the utility needs print styles + @if type-of($utility) == "map" and map-get($utility, print) == true { + @include generate-utility($utility, "-print"); + } + } +} diff --git a/scss/utilities/_background.scss b/scss/utilities/_background.scss deleted file mode 100644 index f9fbb48b9d..0000000000 --- a/scss/utilities/_background.scss +++ /dev/null @@ -1,21 +0,0 @@ -// stylelint-disable declaration-no-important - -@each $color, $value in $theme-colors { - .bg-#{$color} { - background-color: $value !important; - } -} - -@if $enable-gradients { - @each $color, $value in $theme-colors { - @include bg-gradient-variant(".bg-gradient-#{$color}", $value); - } -} - -.bg-white { - background-color: $white !important; -} - -.bg-transparent { - background-color: transparent !important; -} diff --git a/scss/utilities/_borders.scss b/scss/utilities/_borders.scss deleted file mode 100644 index 302f6bf849..0000000000 --- a/scss/utilities/_borders.scss +++ /dev/null @@ -1,75 +0,0 @@ -// stylelint-disable property-blacklist, declaration-no-important - -// -// Border -// - -.border { border: $border-width solid $border-color !important; } -.border-top { border-top: $border-width solid $border-color !important; } -.border-right { border-right: $border-width solid $border-color !important; } -.border-bottom { border-bottom: $border-width solid $border-color !important; } -.border-left { border-left: $border-width solid $border-color !important; } - -.border-0 { border: 0 !important; } -.border-top-0 { border-top: 0 !important; } -.border-right-0 { border-right: 0 !important; } -.border-bottom-0 { border-bottom: 0 !important; } -.border-left-0 { border-left: 0 !important; } - -@each $color, $value in $theme-colors { - .border-#{$color} { - border-color: $value !important; - } -} - -.border-white { - border-color: $white !important; -} - -// -// Border-radius -// - -.rounded-sm { - border-radius: $border-radius-sm !important; -} - -.rounded { - border-radius: $border-radius !important; -} - -.rounded-top { - border-top-left-radius: $border-radius !important; - border-top-right-radius: $border-radius !important; -} - -.rounded-right { - border-top-right-radius: $border-radius !important; - border-bottom-right-radius: $border-radius !important; -} - -.rounded-bottom { - border-bottom-right-radius: $border-radius !important; - border-bottom-left-radius: $border-radius !important; -} - -.rounded-left { - border-top-left-radius: $border-radius !important; - border-bottom-left-radius: $border-radius !important; -} - -.rounded-lg { - border-radius: $border-radius-lg !important; -} - -.rounded-circle { - border-radius: 50% !important; -} - -.rounded-pill { - border-radius: $rounded-pill !important; -} - -.rounded-0 { - border-radius: 0 !important; -} diff --git a/scss/utilities/_display.scss b/scss/utilities/_display.scss deleted file mode 100644 index 217672998b..0000000000 --- a/scss/utilities/_display.scss +++ /dev/null @@ -1,17 +0,0 @@ -// stylelint-disable declaration-no-important - -@each $breakpoint in map-keys($grid-breakpoints) { - @include media-breakpoint-up($breakpoint) { - $infix: breakpoint-infix($breakpoint, $grid-breakpoints); - - @each $value in $displays { - .d#{$infix}-#{$value} { display: $value !important; } - } - } -} - -@media print { - @each $value in $displays { - .d-print-#{$value} { display: $value !important; } - } -} diff --git a/scss/utilities/_flex.scss b/scss/utilities/_flex.scss deleted file mode 100644 index 3d4266e0d0..0000000000 --- a/scss/utilities/_flex.scss +++ /dev/null @@ -1,51 +0,0 @@ -// stylelint-disable declaration-no-important - -// Flex variation -// -// Custom styles for additional flex alignment options. - -@each $breakpoint in map-keys($grid-breakpoints) { - @include media-breakpoint-up($breakpoint) { - $infix: breakpoint-infix($breakpoint, $grid-breakpoints); - - .flex#{$infix}-row { flex-direction: row !important; } - .flex#{$infix}-column { flex-direction: column !important; } - .flex#{$infix}-row-reverse { flex-direction: row-reverse !important; } - .flex#{$infix}-column-reverse { flex-direction: column-reverse !important; } - - .flex#{$infix}-wrap { flex-wrap: wrap !important; } - .flex#{$infix}-nowrap { flex-wrap: nowrap !important; } - .flex#{$infix}-wrap-reverse { flex-wrap: wrap-reverse !important; } - .flex#{$infix}-fill { flex: 1 1 auto !important; } - .flex#{$infix}-grow-0 { flex-grow: 0 !important; } - .flex#{$infix}-grow-1 { flex-grow: 1 !important; } - .flex#{$infix}-shrink-0 { flex-shrink: 0 !important; } - .flex#{$infix}-shrink-1 { flex-shrink: 1 !important; } - - .justify-content#{$infix}-start { justify-content: flex-start !important; } - .justify-content#{$infix}-end { justify-content: flex-end !important; } - .justify-content#{$infix}-center { justify-content: center !important; } - .justify-content#{$infix}-between { justify-content: space-between !important; } - .justify-content#{$infix}-around { justify-content: space-around !important; } - - .align-items#{$infix}-start { align-items: flex-start !important; } - .align-items#{$infix}-end { align-items: flex-end !important; } - .align-items#{$infix}-center { align-items: center !important; } - .align-items#{$infix}-baseline { align-items: baseline !important; } - .align-items#{$infix}-stretch { align-items: stretch !important; } - - .align-content#{$infix}-start { align-content: flex-start !important; } - .align-content#{$infix}-end { align-content: flex-end !important; } - .align-content#{$infix}-center { align-content: center !important; } - .align-content#{$infix}-between { align-content: space-between !important; } - .align-content#{$infix}-around { align-content: space-around !important; } - .align-content#{$infix}-stretch { align-content: stretch !important; } - - .align-self#{$infix}-auto { align-self: auto !important; } - .align-self#{$infix}-start { align-self: flex-start !important; } - .align-self#{$infix}-end { align-self: flex-end !important; } - .align-self#{$infix}-center { align-self: center !important; } - .align-self#{$infix}-baseline { align-self: baseline !important; } - .align-self#{$infix}-stretch { align-self: stretch !important; } - } -} diff --git a/scss/utilities/_float.scss b/scss/utilities/_float.scss deleted file mode 100644 index 54250844ff..0000000000 --- a/scss/utilities/_float.scss +++ /dev/null @@ -1,11 +0,0 @@ -// stylelint-disable declaration-no-important - -@each $breakpoint in map-keys($grid-breakpoints) { - @include media-breakpoint-up($breakpoint) { - $infix: breakpoint-infix($breakpoint, $grid-breakpoints); - - .float#{$infix}-left { float: left !important; } - .float#{$infix}-right { float: right !important; } - .float#{$infix}-none { float: none !important; } - } -} diff --git a/scss/utilities/_overflow.scss b/scss/utilities/_overflow.scss deleted file mode 100644 index 8326c30641..0000000000 --- a/scss/utilities/_overflow.scss +++ /dev/null @@ -1,5 +0,0 @@ -// stylelint-disable declaration-no-important - -@each $value in $overflows { - .overflow-#{$value} { overflow: $value !important; } -} diff --git a/scss/utilities/_shadows.scss b/scss/utilities/_shadows.scss deleted file mode 100644 index f5d03fcd59..0000000000 --- a/scss/utilities/_shadows.scss +++ /dev/null @@ -1,6 +0,0 @@ -// stylelint-disable declaration-no-important - -.shadow-sm { box-shadow: $box-shadow-sm !important; } -.shadow { box-shadow: $box-shadow !important; } -.shadow-lg { box-shadow: $box-shadow-lg !important; } -.shadow-none { box-shadow: none !important; } diff --git a/scss/utilities/_sizing.scss b/scss/utilities/_sizing.scss index f376488022..cc346215b2 100644 --- a/scss/utilities/_sizing.scss +++ b/scss/utilities/_sizing.scss @@ -1,13 +1,5 @@ // stylelint-disable declaration-no-important -// Width and height - -@each $prop, $abbrev in (width: w, height: h) { - @each $size, $length in $sizes { - .#{$abbrev}-#{$size} { #{$prop}: $length !important; } - } -} - .mw-100 { max-width: 100% !important; } .mh-100 { max-height: 100% !important; } diff --git a/scss/utilities/_spacing.scss b/scss/utilities/_spacing.scss deleted file mode 100644 index 351136790a..0000000000 --- a/scss/utilities/_spacing.scss +++ /dev/null @@ -1,73 +0,0 @@ -// stylelint-disable declaration-no-important - -// Margin and Padding - -@each $breakpoint in map-keys($grid-breakpoints) { - @include media-breakpoint-up($breakpoint) { - $infix: breakpoint-infix($breakpoint, $grid-breakpoints); - - @each $prop, $abbrev in (margin: m, padding: p) { - @each $size, $length in $spacers { - .#{$abbrev}#{$infix}-#{$size} { #{$prop}: $length !important; } - .#{$abbrev}t#{$infix}-#{$size}, - .#{$abbrev}y#{$infix}-#{$size} { - #{$prop}-top: $length !important; - } - .#{$abbrev}r#{$infix}-#{$size}, - .#{$abbrev}x#{$infix}-#{$size} { - #{$prop}-right: $length !important; - } - .#{$abbrev}b#{$infix}-#{$size}, - .#{$abbrev}y#{$infix}-#{$size} { - #{$prop}-bottom: $length !important; - } - .#{$abbrev}l#{$infix}-#{$size}, - .#{$abbrev}x#{$infix}-#{$size} { - #{$prop}-left: $length !important; - } - } - } - - // Negative margins (e.g., where `.mb-n1` is negative version of `.mb-1`) - @each $size, $length in $spacers { - @if $size != 0 { - .m#{$infix}-n#{$size} { margin: -$length !important; } - .mt#{$infix}-n#{$size}, - .my#{$infix}-n#{$size} { - margin-top: -$length !important; - } - .mr#{$infix}-n#{$size}, - .mx#{$infix}-n#{$size} { - margin-right: -$length !important; - } - .mb#{$infix}-n#{$size}, - .my#{$infix}-n#{$size} { - margin-bottom: -$length !important; - } - .ml#{$infix}-n#{$size}, - .mx#{$infix}-n#{$size} { - margin-left: -$length !important; - } - } - } - - // Some special margin utils - .m#{$infix}-auto { margin: auto !important; } - .mt#{$infix}-auto, - .my#{$infix}-auto { - margin-top: auto !important; - } - .mr#{$infix}-auto, - .mx#{$infix}-auto { - margin-right: auto !important; - } - .mb#{$infix}-auto, - .my#{$infix}-auto { - margin-bottom: auto !important; - } - .ml#{$infix}-auto, - .mx#{$infix}-auto { - margin-left: auto !important; - } - } -} diff --git a/scss/utilities/_text.scss b/scss/utilities/_text.scss index fbf707d01f..ba775ee8d8 100644 --- a/scss/utilities/_text.scss +++ b/scss/utilities/_text.scss @@ -1,68 +1,7 @@ -// stylelint-disable declaration-no-important - // // Text // -.text-monospace { font-family: $font-family-monospace !important; } - -// Alignment - -.text-justify { text-align: justify !important; } -.text-wrap { white-space: normal !important; } -.text-nowrap { white-space: nowrap !important; } -.text-truncate { @include text-truncate; } - -// Responsive alignment - -@each $breakpoint in map-keys($grid-breakpoints) { - @include media-breakpoint-up($breakpoint) { - $infix: breakpoint-infix($breakpoint, $grid-breakpoints); - - .text#{$infix}-left { text-align: left !important; } - .text#{$infix}-right { text-align: right !important; } - .text#{$infix}-center { text-align: center !important; } - } -} - -// Transformation - -.text-lowercase { text-transform: lowercase !important; } -.text-uppercase { text-transform: uppercase !important; } -.text-capitalize { text-transform: capitalize !important; } - -// Weight and italics - -.font-weight-light { font-weight: $font-weight-light !important; } -.font-weight-lighter { font-weight: $font-weight-lighter !important; } -.font-weight-normal { font-weight: $font-weight-normal !important; } -.font-weight-bold { font-weight: $font-weight-bold !important; } -.font-weight-bolder { font-weight: $font-weight-bolder !important; } -.font-italic { font-style: italic !important; } - -// Contextual colors - -.text-white { color: $white !important; } - @each $color, $value in $theme-colors { @include text-emphasis-variant(".text-#{$color}", $value); } - -.text-body { color: $body-color !important; } -.text-muted { color: $text-muted !important; } - -.text-black-50 { color: rgba($black, .5) !important; } -.text-white-50 { color: rgba($white, .5) !important; } - -// Misc - -.text-decoration-none { text-decoration: none !important; } - -.text-break { - word-break: break-word !important; // IE & < Edge 18 - overflow-wrap: break-word !important; -} - -// Reset - -.text-reset { color: inherit !important; } diff --git a/site/content/docs/4.3/utilities/clearfix.md b/site/content/docs/4.3/helpers/clearfix.md similarity index 95% rename from site/content/docs/4.3/utilities/clearfix.md rename to site/content/docs/4.3/helpers/clearfix.md index d89a55a68c..bbae9a3597 100644 --- a/site/content/docs/4.3/utilities/clearfix.md +++ b/site/content/docs/4.3/helpers/clearfix.md @@ -2,7 +2,8 @@ layout: docs title: Clearfix description: Quickly and easily clear floated content within a container by adding a clearfix utility. -group: utilities +group: helpers +aliases: "/docs/4.3/helpers/" --- Easily clear `float`s by adding `.clearfix` **to the parent element**. Can also be used as a mixin. diff --git a/site/content/docs/4.3/utilities/embed.md b/site/content/docs/4.3/helpers/embed.md similarity index 99% rename from site/content/docs/4.3/utilities/embed.md rename to site/content/docs/4.3/helpers/embed.md index e744f27c0f..f6f69c2dc4 100644 --- a/site/content/docs/4.3/utilities/embed.md +++ b/site/content/docs/4.3/helpers/embed.md @@ -2,7 +2,7 @@ layout: docs title: Embeds description: Create responsive video or slideshow embeds based on the width of the parent by creating an intrinsic ratio that scales on any device. -group: utilities +group: helpers toc: true --- diff --git a/site/content/docs/4.3/helpers/position.md b/site/content/docs/4.3/helpers/position.md new file mode 100644 index 0000000000..921e47a9f5 --- /dev/null +++ b/site/content/docs/4.3/helpers/position.md @@ -0,0 +1,33 @@ +--- +layout: docs +title: Position +description: Use these helpers for quickly configuring the position of an element. +group: helpers +toc: true +--- + +## Fixed top + +Position an element at the top of the viewport, from edge to edge. Be sure you understand the ramifications of fixed position in your project; you may need to add additional CSS. + +{{< highlight html >}} +
...
+{{< /highlight >}} + +## Fixed bottom + +Position an element at the bottom of the viewport, from edge to edge. Be sure you understand the ramifications of fixed position in your project; you may need to add additional CSS. + +{{< highlight html >}} +
...
+{{< /highlight >}} + +## Sticky top + +Position an element at the top of the viewport, from edge to edge, but only after you scroll past it. The `.sticky-top` utility uses CSS's `position: sticky`, which isn't fully supported in all browsers. + +**IE11 and IE10 will render `position: sticky` as `position: relative`.** As such, we wrap the styles in a `@supports` query, limiting the stickiness to only browsers that can render it properly. + +{{< highlight html >}} +
...
+{{< /highlight >}} diff --git a/site/content/docs/4.3/utilities/screen-readers.md b/site/content/docs/4.3/helpers/screen-readers.md similarity index 97% rename from site/content/docs/4.3/utilities/screen-readers.md rename to site/content/docs/4.3/helpers/screen-readers.md index 7781b11fbf..501b9c311c 100644 --- a/site/content/docs/4.3/utilities/screen-readers.md +++ b/site/content/docs/4.3/helpers/screen-readers.md @@ -2,7 +2,7 @@ layout: docs title: Screen readers description: Use screen reader utilities to hide elements on all devices except screen readers. -group: utilities +group: helpers --- Hide an element to all devices **except screen readers** with `.sr-only`. Use `.sr-only-focusable` to show the element only when it's focused (e.g. by a keyboard-only user). Can also be used as mixins. diff --git a/site/content/docs/4.3/utilities/stretched-link.md b/site/content/docs/4.3/helpers/stretched-link.md similarity index 99% rename from site/content/docs/4.3/utilities/stretched-link.md rename to site/content/docs/4.3/helpers/stretched-link.md index ad8a703cad..9b5b3a517c 100644 --- a/site/content/docs/4.3/utilities/stretched-link.md +++ b/site/content/docs/4.3/helpers/stretched-link.md @@ -2,7 +2,7 @@ layout: docs title: Stretched link description: Make any HTML element or Bootstrap component clickable by "stretching" a nested link via CSS. -group: utilities +group: helpers --- Add `.stretched-link` to a link to make its [containing block](https://developer.mozilla.org/en-US/docs/Web/CSS/Containing_block) clickable via a `::after` pseudo element. In most cases, this means that an element with `position: relative;` that contains a link with the `.stretched-link` class is clickable. diff --git a/site/content/docs/4.3/helpers/text.md b/site/content/docs/4.3/helpers/text.md new file mode 100644 index 0000000000..bd57099427 --- /dev/null +++ b/site/content/docs/4.3/helpers/text.md @@ -0,0 +1,25 @@ +--- +layout: docs +title: Text +description: Documentation and examples for common text utilities to control alignment, wrapping, weight, and more. +group: helpers +toc: true +--- + +## Text truncation + +For longer content, you can add a `.text-truncate` class to truncate the text with an ellipsis. **Requires `display: inline-block` or `display: block`.** + +{{< example >}} + +
+
+ Praeterea iter est quasdam res quas ex communi. +
+
+ + + + Praeterea iter est quasdam res quas ex communi. + +{{< /example >}} diff --git a/site/content/docs/4.3/utilities/api.md b/site/content/docs/4.3/utilities/api.md new file mode 100644 index 0000000000..7f587b0b6c --- /dev/null +++ b/site/content/docs/4.3/utilities/api.md @@ -0,0 +1,261 @@ +--- +layout: docs +title: Utility API +description: The utility API is a Sass based tool to generate utility classes. +group: utilities +aliases: "/docs/4.3/utilities/" +toc: true +--- + +The bootstrap utilities are generated with the utility API which can be used to change or extend Bootstraps utility classes. If you don't have any idea what sass maps are, you can consult the [official docs](https://sass-lang.com/documentation/file.SASS_REFERENCE.html#maps) to get started. + +The `$utilities` map contains all utilities and is later merged with your custom `$utilities` map if present. The utility map contains a keyed list of utility groups which accept the following options: + +- `property`: Name of the property, this can be a string or an array of strings (needed for eg. horizontal paddings or margins). +- `responsive` _(optional)_: Boolean indicating if responsive classes need to be generated. `false` by default. +- `class` _(optional)_: Variable to change the class name if you don't want it to be the same as the property. +- `values`: This can be a list of values or a map if you don't want the class name to be the same as the value. If null is used as map key, it isn't rendered. +- `print` _(optional)_: Boolean indicating if print classes need to be generated. `false` by default. + + +## Adding utilities to the utility API + +All utility variables are added to the `$utilities` variable. Custom utility groups can added like this: + +```scss +$utilities: ( + "opacity": ( + property: opacity, + values: ( + 0: 0, + 25: .25, + 50: .5, + 100: 1, + ) + ) + ); +``` + +Output: + +```css +.opacity-0 { + opacity: 0; +} +.opacity-25 { + opacity: .25; +} +.opacity-75 { + opacity: .75; +} +.opacity-100 { + opacity: 1; +} +``` + + +## Changing the class prefix + +With the `class` option, the class prefix can be changed: + +```scss +$utilities: ( + "opacity": ( + property: opacity, + class: o, + values: ( + 0: 0, + 25: .25, + 50: .5, + 100: 1, + ) + ) + ); +``` + +Output: + +```css +.o-0 { + opacity: 0; +} +.o-25 { + opacity: .25; +} +.o-75 { + opacity: .75; +} +.o-100 { + opacity: 1; +} +``` + +## Responsive utilities + +With the `responsive` option, responsive utility classes can be generated: + +```scss +$utilities: ( + "opacity": ( + property: opacity, + responsive: true, + values: ( + 0: 0, + 25: .25, + 50: .5, + 100: 1, + ) + ) + ); +``` + +Output: + +```css +.opacity-0 { + opacity: 0; +} +.opacity-25 { + opacity: .25; +} +.opacity-75 { + opacity: .75; +} +.opacity-100 { + opacity: 1; +} +@media (min-width: 576px) { + .opacity-sm-0 { + opacity: 0; + } + .opacity-sm-25 { + opacity: .25; + } + .opacity-sm-75 { + opacity: .75; + } + .opacity-sm-100 { + opacity: 1; + } +} +@media (min-width: 768px) { + .opacity-md-0 { + opacity: 0; + } + .opacity-md-25 { + opacity: .25; + } + .opacity-md-75 { + opacity: .75; + } + .opacity-md-100 { + opacity: 1; + } +} +@media (min-width: 992px) { + .opacity-lg-0 { + opacity: 0; + } + .opacity-lg-25 { + opacity: .25; + } + .opacity-lg-75 { + opacity: .75; + } + .opacity-lg-100 { + opacity: 1; + } +} +@media (min-width: 1200px) { + .opacity-xl-0 { + opacity: 0; + } + .opacity-xl-25 { + opacity: .25; + } + .opacity-xl-75 { + opacity: .75; + } + .opacity-xl-100 { + opacity: 1; + } +} +``` + +## Changing utilities + +Overriding excising utilities is possible by using the same key. For example if you want more responsive overflow +utility classes you can do this: + +```scss +$utilities: ( + "overflow": ( + responsive: true, + property: overflow, + values: visible hidden scroll auto, + ), +); +``` + + +## Print utilities + +Enabling the `print` option will **also** generate utility classes for print. + +```scss +$utilities: ( + "opacity": ( + property: opacity, + class: o, + print: true, + values: ( + 0: 0, + 25: .25, + 50: .5, + 100: 1, + ) + ) + ); +``` + +Output: + +```css +.o-0 { + opacity: 0; +} +.o-25 { + opacity: .25; +} +.o-75 { + opacity: .75; +} +.o-100 { + opacity: 1; +} + +@media print { + .o-print-0 { + opacity: 0; + } + .o-print-25 { + opacity: .25; + } + .o-print-75 { + opacity: .75; + } + .o-print-100 { + opacity: 1; + } +} +``` + +## Removing utilities + +Utilities can also be removed by changing the group key to `null`: + +```scss +$utilities: ( + "float": null, +); +``` diff --git a/site/content/docs/4.3/utilities/borders.md b/site/content/docs/4.3/utilities/borders.md index 0cb9fc1216..9f082f76a2 100644 --- a/site/content/docs/4.3/utilities/borders.md +++ b/site/content/docs/4.3/utilities/borders.md @@ -3,7 +3,6 @@ layout: docs title: Borders description: Use border utilities to quickly style the border and border-radius of an element. Great for images, buttons, or any other element. group: utilities -aliases: "/docs/4.3/utilities/" toc: true --- diff --git a/site/content/docs/4.3/utilities/position.md b/site/content/docs/4.3/utilities/position.md index 1efaf4cf16..4af457da44 100644 --- a/site/content/docs/4.3/utilities/position.md +++ b/site/content/docs/4.3/utilities/position.md @@ -17,29 +17,3 @@ Quick positioning classes are available, though they are not responsive.
...
...
{{< /highlight >}} - -## Fixed top - -Position an element at the top of the viewport, from edge to edge. Be sure you understand the ramifications of fixed position in your project; you may need to add additional CSS. - -{{< highlight html >}} -
...
-{{< /highlight >}} - -## Fixed bottom - -Position an element at the bottom of the viewport, from edge to edge. Be sure you understand the ramifications of fixed position in your project; you may need to add additional CSS. - -{{< highlight html >}} -
...
-{{< /highlight >}} - -## Sticky top - -Position an element at the top of the viewport, from edge to edge, but only after you scroll past it. The `.sticky-top` utility uses CSS's `position: sticky`, which isn't fully supported in all browsers. - -**IE11 and IE10 will render `position: sticky` as `position: relative`.** As such, we wrap the styles in a `@supports` query, limiting the stickiness to only browsers that can render it properly. - -{{< highlight html >}} -
...
-{{< /highlight >}} diff --git a/site/content/docs/4.3/utilities/text.md b/site/content/docs/4.3/utilities/text.md index 76708e8316..514018e76e 100644 --- a/site/content/docs/4.3/utilities/text.md +++ b/site/content/docs/4.3/utilities/text.md @@ -45,22 +45,6 @@ Prevent text from wrapping with a `.text-nowrap` class. {{< /example >}} -For longer content, you can add a `.text-truncate` class to truncate the text with an ellipsis. **Requires `display: inline-block` or `display: block`.** - -{{< example >}} - -
-
- Praeterea iter est quasdam res quas ex communi. -
-
- - - - Praeterea iter est quasdam res quas ex communi. - -{{< /example >}} - ## Word break Prevent long strings of text from breaking your components' layout by using `.text-break` to set `overflow-wrap: break-word` (and `word-break: break-word` for IE & Edge compatibility). diff --git a/site/data/nav.yml b/site/data/nav.yml index 596e3faea3..3851fa206f 100644 --- a/site/data/nav.yml +++ b/site/data/nav.yml @@ -53,22 +53,28 @@ - title: Toasts - title: Tooltips +- title: Helpers + pages: + - title: Clearfix + - title: Embed + - title: Position + - title: Screen readers + - title: Stretched link + - title: Text + - title: Utilities pages: + - title: API - title: Borders - - title: Clearfix - title: Colors - title: Display - - title: Embed - title: Flex - title: Float - title: Overflow - title: Position - - title: Screen readers - title: Shadows - title: Sizing - title: Spacing - - title: Stretched link - title: Text - title: Vertical align - title: Visibility