Style
When developing frontend applications, it is crucial to create a sense of stylistic unity and cohesion that gives users a better, smoother experience. Achieving this goal can be tricky in the micro-frontend world, where all the moving parts are not built together and often cannot rely on the same stylistic definitions.
micro-lc helps you make sure that all orchestrated pieces feel alike supporting various means of style declaration and offering some out-of-the-box utilities.
Styling applications
When styling micro-lc applications, one key factor to consider is whether Shadow DOM is enabled or not.
If Shadow DOM is enabled, the application layout is put inside of micro-lc shadow root, while the content is not, meaning that their respective styles are encapsulated and cannot affect one another. Furthermore, "global" document styles (e.g., style tags in document head) do not influence layout – or any other node in a shadow root, even if it is placed in content –.
On the other hand, if micro-lc Shadow DOM is disabled, both layout and content are placed in regular DOM and are always affected by the same styling rules.
Although partially supported in micro-lc v1,
v2 does operate a complete separation of concerns between layout,
routing, and UI components. dark mode
features are completely delegated to layout and micro-lc API application
interactions.
Sample micro-lc components do not support dark mode
Style declarations
style
attribute
The style
attribute is available to all
HTML elements and enable fine-grained, encapsulating styling. It can be used when
composing resources declaring it alongside other attributes.
layout:
content: |
<div style="color: red;">This will be red</div>
applications:
home:
integrationMode: compose
route: ./
config:
content:
- tag: div
attributes:
style: "color: orange;"
content: This will be orange
Since it affects only the element to which it belongs and its children, the style
attribute works the same with or
without Shadow DOM enabled.
Style information elements
The <style>
HTML element can be used to style a
document without recurring to external sources.
If a <style>
tag is placed outside a shadow-root, it effects all the elements rendered in the regular DOM. If it
is places inside a shadow-root, it effects only the elements in the same shadow-root. <style>
tags can be either
declared in the index.html
or constructed when composing components.
- index.html
- micro-lc.config.yaml
<!doctype html>
<html lang="en">
<head>
<title>Style information elements</title>
<style>
div {
background: red;
}
</style>
<script async type="module" src="https://cdn.jsdelivr.net/npm/@micro-lc/orchestrator@latest/dist/micro-lc.production.js"></script>
</head>
<body>
<micro-lc config-src="./config.yaml"></micro-lc>
</body>
</html>
layout:
content:
- tag: style
content: "div: { color: orange; }"
- tag: div
content: This will be orange and WILL NOT have a red background
applications:
home:
integrationMode: compose
route: ./
config:
content:
- tag: style
content: "div: { color: green; }"
- tag: div
content: This will be green and WILL have a red background
External stylesheets
External stylesheets are referenced through
<link>
HTML elements. They behave the same way as
style information elements: they effect only elements in the same DOM and can be
declared in the index.html
or constructed when composing
components.
- index.html
- micro-lc.config.yaml
<!doctype html>
<html lang="en">
<head>
<title>Style information elements</title>
<link rel="stylesheet" href="./my-stylesheet-1.css">
<script async type="module" src="https://cdn.jsdelivr.net/npm/@micro-lc/orchestrator@latest/dist/micro-lc.production.js"></script>
</head>
<body>
<micro-lc config-src="./config.yaml"></micro-lc>
</body>
</html>
layout:
content:
- tag: link
attributes:
rel: stylesheet
href: ./my-stylesheet-2.css
- tag: div
content: This will be effected by "my-stylesheet-2.css" and NOT by "my-stylesheet-1.css"
applications:
home:
integrationMode: compose
route: ./
config:
content:
- tag: link
attributes:
rel: stylesheet
href: ./my-stylesheet-3.css
- tag: div
content: This will be effected by "my-stylesheet-3.css" AND by "my-stylesheet-1.css"
Style injection
micro-lc API provides to a way to inject style at runtime with the
setStyle
method, implementing the following interface:
type SetStyle = (styles: CSSConfig) => void
interface CSSConfig {
global?: Record<string, string | number>
nodes?: Record<string, Record<string, string | number>>
}
Global style
Global style is injected in the uppermost selector, which is :host
if micro-lc is in Shadow DOM mode and
:root
(which in most cases is head
) if it is not. This behaviour is useful to set global
CSS variables that can be used to enforce
a consistent theme thought the whole application.
For example, after an application or a component has made this call:
microlcApi.getExtensions().css.setStyle({
global: {
'--my-application-color': 'red'
}
})
each node parented by micro-lc can use var(--my-application-color)
to access the global variable in its
own CSS, whether it is in a shadow-root or not.
Nodes styling
With the node
property of setStyle
argument, specific CSS selectors can be constructed and injected in DOM. These
selectors are effected by Shadow DOM, meaning they apply only on elements in the same DOM (just like
style information elements).
For example, after an application or a component has made this call:
microlcApi.getExtensions().css.setStyle({
nodes: {
p: {
color: 'red'
}
}
})
all <p>
elements in the same DOM of the call will be red.
Dark mode
micro-lc is agnostic in terms of dark-mode support, meaning that since it controls only page layout, any kind of dark-mode support must be enabled via web-components composing the layout and parcels/compose applications. Notice that the iframe integration mode will not be able to support any kind of style injection due its complete sandboxing and encapsulation.
A good reference for implementing dark mode in your components can be found with the ionic framework:
We briefly remind here that UA compatibility can be ensured by using meta
tags in index.html
of your micro-lc
orchestrated application like:
<meta name="color-scheme" content="dark light" />
this is recommended by HTML specification and has fairly good browser support.
In order to use OS-provided color scheme preferences, it can be helpful the media
query construct
@media (prefers-color-scheme: light) {
body {
--text-color: #eee;
--bkg-color: #121212;
}
}
which works inside web-components: even within their shadow-dom by evaluating
window.matchMedia('(prefers-color-scheme: light)')
which has fairly good browser support.
In order to build theme switch buttons, we recommend using micro-lc api
by, for instance, setting CSS variables when using webcomponents with shadow-dom or CSS classes for the <body>
tag or attribute of html
, which though
will not work inside a shadow-dom of a web-component.