|

Utility API

UX4g utilities are produced by the utility API and may be used with Sass to change or add to the standard set of utility classes. Our utility API is built using a number of Sass functions and maps to create families of classes with different parameters. If you're not familiar with Sass maps, start by reading the official Sass docs.

All of the utilities are included in the $utilities map, which is later combined with any existing bespoke $utilities maps. A keyed list of utility groups that accept the following choices is included in the utility map.

Option Type Default value Description
property Required Name of the property, this can be a string or an array of strings (e.g., horizontal paddings or margins).
values Required 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, class is not prepended to the class name.
class Optional null Name of the generated class. If not provided and property is an array of strings, class will default to the first element of the property array. If not provided and property is a string, the values keys are used for the class names.
css-var Optional false Boolean to generate CSS variables instead of CSS rules.
css-variable-name Optional null Custom un-prefixed name for the CSS variable inside the ruleset.
local-vars Optional null Map of local CSS variables to generate in addition to the CSS rules.
state Optional null List of pseudo-class variants (e.g., :hover or :focus) to generate.
responsive Optional false Boolean indicating if responsive classes should be generated.
rfs Optional false Boolean to enable fluid rescaling with RFS.
print Optional false Boolean indicating if print classes need to be generated.
rtl Optional true Boolean indicating if utility should be kept in RTL.

API explained #

Within our _utilities.scss stylesheet, all utility variables are added to the $utilities variable. Each utility group resembles the following:

$utilities: (
  "opacity": (
    property: opacity,
    values: (
      0: 0,
      25: .25,
      50: .5,
      75: .75,
      100: 1,
    )
  )
);

Which outputs the following:

.opacity-0 { opacity: 0; }
.opacity-25 { opacity: .25; }
.opacity-50 { opacity: .5; }
.opacity-75 { opacity: .75; }
.opacity-100 { opacity: 1; }

Property #

Any utility must have the required property key set, and it must have a valid CSS property in it. The ruleset for the created utility makes use of this feature. The class name acts as the default class name when the class key is absent. Think about the text-decoration tool:

$utilities: (
  "text-decoration": (
    property: text-decoration,
    values: none underline line-through
  )
);
RESULT
.text-decoration-none { text-decoration: none !important; }
.text-decoration-underline { text-decoration: underline !important; }
.text-decoration-line-through { text-decoration: line-through !important; }

Values #

To define which values for the specified property should be used in the automatically created class names and rules, use the values key. (Set in the utilities or in a Sass variable) Can be a list or map.

values: none underline line-through

As a map, like with opacity utilities:

values: (
  0: 0,
  25: .25,
  50: .5,
  75: .75,
  100: 1,
)

As a Sass variable that sets the list or map, as in our position utilities:

values: $position-values

Class #

Use the class option to change the class prefix used in the compiled CSS. For example, to change from .opacity-* to .o-*:

$utilities: (
  "opacity": (
    property: opacity,
    class: o,
    values: (
      0: 0,
      25: .25,
      50: .5,
      75: .75,
      100: 1,
    )
  )
);
RESULT
.o-0 { opacity: 0 !important; }
.o-25 { opacity: .25 !important; }
.o-50 { opacity: .5 !important; }
.o-75 { opacity: .75 !important; }
.o-100 { opacity: 1 !important; }

If class: null, generates classes for each of the values keys:

$utilities: (
  "visibility": (
    property: visibility,
    class: null,
    values: (
      visible: visible,
      invisible: hidden,
    )
  )
);
RESULT
.visible { visibility: visible !important; }
.invisible { visibility: hidden !important; }

CSS variable utilities #

If the css-var boolean option is set to true, local CSS variables rather than the customary property: value rules will be generated by the API for the specified selector. To set a CSS variable name other from the class name, add an optional css-variable-name.

Take a look at our .text-opacity-* tools. We will receive a customized result if include the css-variable-name option.

$utilities: (
  "text-opacity": (
    css-var: true,
    css-variable-name: text-alpha,
    class: text-opacity,
    values: (
      25: .25,
      50: .5,
      75: .75,
      100: 1
    )
  ),
);
RESULT
.text-opacity-25 { --bs-text-alpha: .25; }
.text-opacity-50 { --bs-text-alpha: .5; }
.text-opacity-75 { --bs-text-alpha: .75; }
.text-opacity-100 { --bs-text-alpha: 1; }

Local CSS variables #

To create local CSS variables for the utility class's ruleset, use the local-vars option to specify a Sass map. Please be aware that consuming certain local CSS variables in the resulting CSS rules may necessitate additional effort. Consider our .bg-* tools, for instance:

$utilities: (
  "background-color": (
    property: background-color,
    class: bg,
    local-vars: (
      "bg-opacity": 1
    ),
    values: map-merge(
      $utilities-bg-colors,
      (
        "transparent": transparent
      )
    )
  )
);
RESULT
.bg-primary {
  --bs-bg-opacity: 1;
  background-color: rgba(var(--bs-primary-rgb), var(--bs-bg-opacity)) !important;
}

States #

To create variations of pseudo-classes, use the state option. The pseudo-classes hover and focus are two examples. Classnames are generated for that pseudo-class when a list of states is given. For instance, adding state: hover will modify the opacity on hover .opacity-hover :hover in the CSS code you generated.

Need more than one pseudo-class? Use a list of states, separated by spaces: state: focused hover.

$utilities: (
  "opacity": (
    property: opacity,
    class: opacity,
    state: hover,
    values: (
      0: 0,
      25: .25,
      50: .5,
      75: .75,
      100: 1,
    )
  )
);
RESULT
.opacity-0-hover:hover { opacity: 0 !important; }
.opacity-25-hover:hover { opacity: .25 !important; }
.opacity-50-hover:hover { opacity: .5 !important; }
.opacity-75-hover:hover { opacity: .75 !important; }
.opacity-100-hover:hover { opacity: 1 !important; }

Responsive #

Add the responsive boolean to generate responsive utilities (e.g., .opacity-md-25) across all breakpoints.

$utilities: (
  "opacity": (
    property: opacity,
    responsive: true,
    values: (
      0: 0,
      25: .25,
      50: .5,
      75: .75,
      100: 1,
    )
  )
);
RESULT
.opacity-0 { opacity: 0 !important; }
.opacity-25 { opacity: .25 !important; }
.opacity-50 { opacity: .5 !important; }
.opacity-75 { opacity: .75 !important; }
.opacity-100 { opacity: 1 !important; }

@media (min-width: 576px) {
  .opacity-sm-0 { opacity: 0 !important; }
  .opacity-sm-25 { opacity: .25 !important; }
  .opacity-sm-50 { opacity: .5 !important; }
  .opacity-sm-75 { opacity: .75 !important; }
  .opacity-sm-100 { opacity: 1 !important; }
}

@media (min-width: 768px) {
  .opacity-md-0 { opacity: 0 !important; }
  .opacity-md-25 { opacity: .25 !important; }
  .opacity-md-50 { opacity: .5 !important; }
  .opacity-md-75 { opacity: .75 !important; }
  .opacity-md-100 { opacity: 1 !important; }
}

@media (min-width: 992px) {
  .opacity-lg-0 { opacity: 0 !important; }
  .opacity-lg-25 { opacity: .25 !important; }
  .opacity-lg-50 { opacity: .5 !important; }
  .opacity-lg-75 { opacity: .75 !important; }
  .opacity-lg-100 { opacity: 1 !important; }
}

@media (min-width: 1200px) {
  .opacity-xl-0 { opacity: 0 !important; }
  .opacity-xl-25 { opacity: .25 !important; }
  .opacity-xl-50 { opacity: .5 !important; }
  .opacity-xl-75 { opacity: .75 !important; }
  .opacity-xl-100 { opacity: 1 !important; }
}

@media (min-width: 1400px) {
  .opacity-xxl-0 { opacity: 0 !important; }
  .opacity-xxl-25 { opacity: .25 !important; }
  .opacity-xxl-50 { opacity: .5 !important; }
  .opacity-xxl-75 { opacity: .75 !important; }
  .opacity-xxl-100 { opacity: 1 !important; }
}

Print #

When the print option is enabled, utility classes for print are also generated. These classes can only be used with the @media print ... media query.

$utilities: (
  "opacity": (
    property: opacity,
    print: true,
    values: (
      0: 0,
      25: .25,
      50: .5,
      75: .75,
      100: 1,
    )
  )
);
RESULT
.opacity-0 { opacity: 0 !important; }
.opacity-25 { opacity: .25 !important; }
.opacity-50 { opacity: .5 !important; }
.opacity-75 { opacity: .75 !important; }
.opacity-100 { opacity: 1 !important; }

@media print {
  .opacity-print-0 { opacity: 0 !important; }
  .opacity-print-25 { opacity: .25 !important; }
  .opacity-print-50 { opacity: .5 !important; }
  .opacity-print-75 { opacity: .75 !important; }
  .opacity-print-100 { opacity: 1 !important; }
}

Importance #

Each and every utility produced by the API includes! It's crucial to make sure they override modifier classes and components as intended. The global switch for this option is the $enable-important-utilities variable, which has a default value of true.

Using the API #

Now that you’re familiar with how the utilities API works, learn how to add your own custom classes and modify our default utilities.

Override utilities #

Use the same key to override current utilities. For instance, follow these steps if there is a need for more responsive overflow utility classes:

$utilities: (
  "overflow": (
    responsive: true,
    property: overflow,
    values: visible hidden scroll auto,
  ),
);

Add utilities #

With a map-merge, new utilities can be added to the default $utilities map. Prior to adding the new utilities, make sure our necessary Sass files and _utilities.scss are imported. Here's an example of how to implement a cursor utility that responds to three values.

@import "UX4G/scss/functions";
@import "UX4G/scss/variables";
@import "UX4G/scss/maps";
@import "UX4G/scss/mixins";
@import "UX4G/scss/utilities";

$utilities: map-merge(
  $utilities,
  (
    "cursor": (
      property: cursor,
      class: cursor,
      responsive: true,
      values: auto pointer grab,
    )
  )
);

@import "UX4G/scss/utilities/api";

Modify utilities #

Use the map-get and map-merge functions to change the utilities already present in the default $utilities map. The width utilities are being given an additional value in the example below. First, perform a basic map merging, and then indicate which utility per wish to change. From there, use map-get to access and change the utility's settings and values by fetching the nested "width" map.

@import "ux4g/scss/functions";
@import "ux4g/scss/variables";
@import "ux4g/scss/maps";
@import "ux4g/scss/mixins";
@import "ux4g/scss/utilities";

$utilities: map-merge(
  $utilities,
  (
    "width": map-merge(
      map-get($utilities, "width"),
      (
        values: map-merge(
          map-get(map-get($utilities, "width"), "values"),
          (10: 10%),
        ),
      ),
    ),
  )
);

@import "ux4g/scss/utilities/api";

Enable responsive #

An existing collection of utilities that are not responsive by default can be made responsive by enabling responsive classes. For instance, to enable responsive border classes:

@import "ux4g/scss/functions";
@import "ux4g/scss/variables";
@import "ux4g/scss/maps";
@import "ux4g/scss/mixins";
@import "ux4g/scss/utilities";

$utilities: map-merge(
  $utilities, (
    "border": map-merge(
      map-get($utilities, "border"),
      ( responsive: true ),
    ),
  )
);

@import "ux4g/scss/utilities/api";

For each breakpoint, this will now produce responsive variants of .border and .border-0. The produced CSS will seem as follows:

.border { ... }
.border-0 { ... }

@media (min-width: 576px) {
  .border-sm { ... }
  .border-sm-0 { ... }
}

@media (min-width: 768px) {
  .border-md { ... }
  .border-md-0 { ... }
}

@media (min-width: 992px) {
  .border-lg { ... }
  .border-lg-0 { ... }
}

@media (min-width: 1200px) {
  .border-xl { ... }
  .border-xl-0 { ... }
}

@media (min-width: 1400px) {
  .border-xxl { ... }
  .border-xxl-0 { ... }
}

Rename utilities #

Missing v4 utilities or accustomed to a different name scheme? The utilities API can be used to change a utility's resultant class, such as renaming .ms-* utilities to the somewhat-outdated .ml-*:

@import "ux4g/scss/functions";
@import "ux4g/scss/variables";
@import "ux4g/scss/maps";
@import "ux4g/scss/mixins";
@import "ux4g/scss/utilities";

$utilities: map-merge(
  $utilities, (
    "margin-start": map-merge(
      map-get($utilities, "margin-start"),
      ( class: ml ),
    ),
  )
);

@import "ux4g/scss/utilities/api";

Remove utilities #

Remove any of the default utilities with the map-remove() Sass function.

@import "ux4g/scss/functions";
@import "ux4g/scss/variables";
@import "ux4g/scss/maps";
@import "ux4g/scss/mixins";
@import "ux4g/scss/utilities";

// Remove multiple utilities with a comma-separated list
$utilities: map-remove($utilities, "width", "float");

@import "ux4g/scss/utilities/api";

You can also use the map-merge() Sass function and set the group key to null to remove the utility.

@import "ux4g/scss/functions";
@import "ux4g/scss/variables";
@import "ux4g/scss/maps";
@import "ux4g/scss/mixins";
@import "ux4g/scss/utilities";

$utilities: map-merge(
  $utilities,
  (
    "width": null
  )
);

@import "ux4g/scss/utilities/api";

Add, remove, modify #

With the map-merge() Sass function, there is an option to change numerous utilities at once and add, remove, and alter them all. Here's how to integrate the prior illustrations into one sizable map.

@import "ux4g/scss/functions";
@import "ux4g/scss/variables";
@import "ux4g/scss/maps";
@import "ux4g/scss/mixins";
@import "ux4g/scss/utilities";

$utilities: map-merge(
  $utilities,
  (
    // Remove the `width` utility
    "width": null,

    // Make an existing utility responsive
    "border": map-merge(
      map-get($utilities, "border"),
      ( responsive: true ),
    ),

    // Add new utilities
    "cursor": (
      property: cursor,
      class: cursor,
      responsive: true,
      values: auto pointer grab,
    )
  )
);

@import "ux4g/scss/utilities/api";

Remove utility in RTL #

RTL styling might be challenging in some edge instances, such as Arabic line breaks. Thus, by changing the rtl option to false, utilities can be removed from RTL output:

$utilities: (
  "word-wrap": (
    property: word-wrap word-break,
    class: text,
    values: (break: break-word),
    rtl: false
  ),
);
RESULT
/* rtl:begin:remove */
.text-break {
  word-wrap: break-word !important;
  word-break: break-word !important;
}
/* rtl:end:remove */

This doesn’t output anything in RTL, thanks to the RTLCSS remove control directive.