DEV Community

Brian Neville-O'Neill
Brian Neville-O'Neill

Posted on • Originally published at blog.logrocket.com on

Custom responsive behaviour using custom CSS properties

Today, custom CSS properties are only used as CSS variables. Here is how to actually define custom responsive behaviour using custom CSS properties.

Custom properties have been introduced as “variables” in the CSS Variables Module in 2012. Later, “variables” were renamed “custom properties“ which according to the CSS Spec will support “other things” than variable substitution.

These “other things” don’t seem to have happened until now. The module is still a candidate recommendation since 2015, though major browsers support it.

Custom properties can be used like usual CSS properties. They are defined by two leading dashes followed by an identifier of your choice and can be defined inside any CSS block:

.some-selector {
  --my-var: value;
}
Enter fullscreen mode Exit fullscreen mode

The value can be any expression that would be valid for a CSS property.

Custom properties take part in the cascade, i.e. they are inherited and can be used inside media query blocks. To use --my-var as a variable you simply reference it in a value of another property:

.other-selector {
  background-color: var(--my-var);
}
Enter fullscreen mode Exit fullscreen mode

For a more exhaustive description of the “variable” usage look here: https://developer.mozilla.org/en-US/docs/Web/CSS/Using_CSS_variables

The problem with the “other things”

When you define your new custom property in CSS and don’t use it in a var() expression, nobody is going to listen. So no custom layout or behaviour will arise from it. Of course, it is possible to retrieve the value of a custom property for a given element from JavaScript:

window.getComputedStyle(element).getPropertyValue("--my-var");
Enter fullscreen mode Exit fullscreen mode

This is great but does not necessarily make sense. In JavaScript, you can program a custom behaviour for elements directly, instead of defining a custom property for the given selector in CSS and then reading this property using the above code and programming the custom behaviour based in the read value.

You could use media queries to create responsive behaviour. The value read by getPropertyValue would then depend on the current metrics of the browser. This can also be achieved in JavaScript directly, by querying the browser metrics directly in your code or by using matchMedia to see what media queries currently apply.

Where it really makes sense: frameworks

When you are writing your own code, custom CSS properties are not much help. This is however very different if you understand them as an API to a framework that provides custom behaviour. Here, the programmer of the behaviour (framework) and the user are different people. So, the user wouldn’t necessarily want to dig into the code to modify the behaviour.

Many frameworks today are controlled by CSS classes (e.g. Bootstrap or Bulma) or HTML attributes (Angular, Vue). Custom CSS properties are a 3rd way for specifying parameters and may prove to be a very efficient way to define responsive behaviour.

In the next chapter, the possibilities of custom CSS properties are explained in the layJS framework example.

Responsive animated UIs with layerJS

LayerJS is a framework to create animated layered user interfaces with simple HTML markup. It provides a universal concept where common UI pattern (menus, sliders, accordions, parallax, zooming) can simply be defined as dynamic, overlapping layers.

Its behaviour can be controlled by HTML attributes or alternatively by the custom CSS properties described above. In the following chapter, we use this to create a menu which moves in from the side on desktops while fading in as fullscreen on mobile.

Creating a side menu

In layerJS everything happens in a “stage”. A stage is a viewport which defines the area where a thing should happen. In our case we want everything to happen right in the browser window, so we define the body as a stage.

We want the menu to appear on top of the main content, so we define two layers inside the stage, one for the menu and one for the content.

Within the menu layer we create a “frame” which contains the actual content of the menu and within the content layer we create a frame with our page content.

We don‘t want to show the menu initially we set the default frame of the menu layer to “!none”:

<body lj-type="stage">
  <div id="lcontent" lj-type="layer">
    <div id="home" lj-type="frame">
      ... content ...
    </div>
    ... optional: more content frames
  </div>
  <div id="lmenu" lj-type="layer" lj-default-frame="!none">
    <div id="menu" lj-type="frame">
      ... menu items
    </div>
  </div>
</div>
Enter fullscreen mode Exit fullscreen mode

Now we define the behaviour of our UI. The behaviour is basically how the frames are fit/positioned into the stage and how this is animated. We chose to show the menu on the left side at full browser height with a fixed width. This is done by setting lj-fit-to to responsive-height. The transition is defined by lj-transition:

#menu {
  --lj-fit-to: responsive-height;
  --lj-transition: left;
  width: 200px;
}
Enter fullscreen mode Exit fullscreen mode

Make it responsive

To make this behaviour responsive we simply define CSS clauses for mobile screens with different parameters — the menu should fill the whole screen and it should fade in:

@media (max-width: 600px) {
  #menu {
    --lj-fit-to: responsive;
    --lj-transition: fade;
  }
}
Enter fullscreen mode Exit fullscreen mode

You can find a live example here on JSBin. Click on “Menu” to open and close it. Make sure to resize the output part to see the responsive behaviour.

This example shows how custom CSS properties can serve as a convenient method to control framework behaviour in a responsive way. The biggest advantage is that the framework does not have to make any assumption about how responsiveness should work in a particular situation. The user will most likely work with a grid system or at least a set of breakpoints and the framework will seamlessly integrate into that concept.

Conclusion

layerJS in particular benefits from custom CSS properties. It provides a concept to build arbitrary user interfaces out of nested layers. It doesn’t directly implement responsive features but leaves the decision to the user on how the content of the layers should look on different devices.

With custom CSS properties the user can not only define the layout but also the behaviour in a responsive way. For an explanation of the layerJS concept have a look at the animation on the project homepage. An easy introduction on how to build UIs with layerJS can be found here.


Plug: LogRocket, a DVR for web apps

https://logrocket.com/signup/

LogRocket is a frontend logging tool that lets you replay problems as if they happened in your own browser. Instead of guessing why errors happen, or asking users for screenshots and log dumps, LogRocket lets you replay the session to quickly understand what went wrong. It works perfectly with any app, regardless of framework, and has plugins to log additional context from Redux, Vuex, and @ngrx/store.

In addition to logging Redux actions and state, LogRocket records console logs, JavaScript errors, stacktraces, network requests/responses with headers + bodies, browser metadata, and custom logs. It also instruments the DOM to record the HTML and CSS on the page, recreating pixel-perfect videos of even the most complex single page apps.

Try it for free.


The post Custom responsive behaviour using custom CSS properties appeared first on LogRocket Blog.

Top comments (0)