1.0.0 • Published 10 months ago

@simulacron/r-layout v1.0.0

Weekly downloads
-
License
BSD-3-Clause
Repository
github
Last release
10 months ago

R-Layout - Adaptive layouts in SCSS

[ ENGLISH | RUSSIAN ]

The package allows you to define a set of parameters for adaptive user interface components.

For example, you need to create an information block with a heading and text:

<div class="block">

  <!-- Heading -->
  <div class="block-heading">
    Heading
  </div>

  <!-- Text -->
  <div class="block-text">
    Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Sed dapibus, ante ultricies adipiscing pulvinar, enim tellus volutpat odio, vel pretium ligula purus vel ligula.
  </div>

</div>

This block must be adaptive, i.e. have different margins and font sizes for different breakpoints.

Usually in SCSS this is implemented like this:

.block {

  // Heading styling
  .block-heading {

    // Styles for small screens
    @media only screen and (max-width: 767px) {
      font-size: 18px;
      line-height: 1.3;
      margin-bottom: 24px;
    }

    // Styles for big screens
    @media only screen and (min-width: 768px) {
      font-size: 20px;
      line-height: 1.2;
      margin-bottom: 32px;
    }

  }

  // Text styling
  .block-text {

    // Styles for small screens
    @media only screen and (max-width: 767px) {
      font-size: 16px;
    }

    // Styles for big screens
    @media only screen and (min-width: 768px) {
      font-size: 18px;
      line-height: 1.3;
    }

  }

}

With R-Layout this can be defined like this:

@include rl.define-layout(
  // Layout name
  $name: 'block',

  // Breakpoints
  $sizes: (
    small:    (max: 767px),
    large:   (min: 768px),
  ),

  // Layout parameter values
  $values: (

    // Small screen parameters
    small: (

      // Heading parameters
      heading: (
        font-size: 18px,
        line-height: 1.3,
        margin: (
          bottom: 24px,
        ),
      ),

      // Text parameters
      text: (
        font-size: 16px,
      ),

    ),

    // Large screen parameters
    large: (

      // Heading parameters
      heading: (
        font-size: 20px,
        line-height: 1.2,
        margin: (
          bottom: 32px,
        ),
      ),

      // Text parameters
      text: (
        font-size: 18px,
        line-height: 1.3,
      ),

    ),

  ),
);

.block {

  @include rl.layout(block) {

    // Heading styling
    .block-heading {
      font-size: rl.value(heading, font-size);
      line-height: rl.value(heading, line-height);
      margin-bottom: rl.value(heading, margin, bottom);
    }

    // Text styling
    .block-text {
      font-size: rl.value(text, font-size);
      line-height: rl.value(text, line-height);
    }

  }

}

Thus, it simplifies the management of adaptive layout, for example, you can easily change breakpoints in a single place or even add another one, and it is also easier to change some layout parameters, such as margins or font size.

Installation

You can install the package via NPM:

npm install @simulacron/r-layout

After that, you need to add the ./node_modules path to the --load-path= parameter when calling sass:

sass --load-path=./node_modules styles.scss:styles.css

Now you can use r-layout in your scss.

Import with @use

When imported via @use, mixins and functions will be available in the rl namespace:

@use "@simulacron/r-layout/rl";

@include rl.define-layout(
  ...
);

...

@include rl.layout(...) {

  font-size: rl.value(...);

}

Import with @import

When importing via @import, mixins and functions in the global namespace will be available:

@import '@simulacron/r-layout';

@include r-define-layout(
  ...
);

...

@include r-layout(...) {

  font-size: rl-value(...);

}

Mapping names of mixins and functions

Please note that mixins and functions have different names for different import methods. Below is a table of name mappings for different import methods:

@use@import
rl.define-layoutr-define-layout
rl.layoutr-layout
rl.valuerl-value
rl.def-valuerl-def-value
rl.layout-valuerl-layout-value
rl.layout-def-valuerl-layout-def-value

Usage

First you need to define the layout and its parameters, and then you can use the layout to generate blocks of media queries.

Layout definition (define-layout)

The layout is defined using the rl.define-layout(...) mixin.

@include rl.define-layout(
  $name: 'intro',
  $sizes: (
    small:    (max: 767px),
    large:   (min: 768px),
  ),
  $values: (
    small: (
      font-size: 16px,
    ),
    large: (
      font-size: 18px,
    ),
  ),
);

The mixin has 3 required parameters:

  • $name - layout name, used in rl.layout(...);
  • $sizes - layout breakpoints;
  • $values - layout parameters.

Breakpoints

Breakpoints $sizes are specified as a Map with a list of breakpoint names and media query conditions:

(
  breakpoint-name: (
    min: XX,
    max: YY,
    orientation: ZZ
  )
)

Breakpoint names are used when specifying layout parameters for each breakpoint.

Conditions for a media query are specified using three values:

  • min - minimum screen width;
  • max - maximum screen width;
  • orientation - screen orientation.

Attention! All values are optional, but at least one must always be specified.

For example, if you specify:

(
  small: (max: 767px),
  medium: (min: 768px, max: 1023px),
  large: (min: 1024px),
)

...this would be equivalent to:

@media screen and (max-width: 767px) {...}
@media screen and (min-width: 768px, max-width: 1023px) {...}
@media screen and (min-width: 1024px) {...}

Layout parameters

Layout parameters are set in $values as a Map for each breakpoint defined in $sizes:

(
  small: (...),
  large: (...),
)

For a breakpoint, a parameter map is specified in an arbitrary format. Parameter map supports nested maps:

small: (
  font-size: 16px,
  spacing: (
    v-spacing: 24px,
  ),
),

The set of parameters for different breakpoints may differ. For example, a breakpoint for narrow screens may not have a horizontal spacing parameter. In this case, the rl.value(...) function will return null for a parameter missing in the breakpoint parameters and the CSS property will not be generated.

(
  small: (
    font-size: 16px,
    spacing: (
      // h-spacing is not specified for this breakpoint
      v-spacing: 24px,
    ),
  ),
  large: (
    font-size: 18px,
    spacing: (
      h-spacing: 16px,
      v-spacing: 24px,
    ),
  ),
)

Using the layout (layout)

Once a layout is defined, it can be used to generate media query blocks using the rl.layout(...) mixin.

Inside the layout, to get the parameter, you need to use the rl.value(...) function:

.selector {

  @include rl.layout(block) {
    font-size: rl.value(font-size);
  }

}

Attention! Since the @rl-layout(...) mixin repeats its content for each breakpoint, only adaptive CSS constructs should be placed inside it.

If a layout parameter is nested (a map within a map), to access such a parameter, you need to pass the entire path to it in the rl.value(...) function (as sequential parameters), for example:

@include rl.define-layout(
  ...
  // Parameter defined as nested map
  spacing: (
    top: 32px,
    bottom: 64px,
  )
  ...
);

@include rl.layout(...) {
  // Getting the value of the bottom parameter in spacing
  margin-bottom: rl.value(spacing, bottom);
}

Nesting of parameters can be any depth.

If the parameter is not found in the layout, then the function will return null.

Using layout parameters in math expressions

When using parameters inside a mathematical expression, an error may occur if the parameter is not present in one of the breakpoints or if it is equal to zero (division-by-zero error). To avoid such errors, in mathematical expressions, instead of the rl.value(...) function, use the rl.def-value(...) function, in which the default value is passed in the first parameter:

width: (100% / rl.def-value(1, columns-count));