Skip to main content

Styling

CSS Modules

tramvai provides CSS Modules as default approach for styling. Any imports of CSS files as JS modules will be processed as CSS Modules, for example if we try to create a Button component:

Button.tsx
import styles from './Button.module.css';

export const Button = () => <button className={styles.button} />;
tip

It is not required at this moment, but prefer use .module.css suffix for CSS files - in a future releases only filenames with this pattern will be processed as CSS Modules

Global styles

All *.css file imports will be treated as CSS Modules by default. To disable CSS Modules processing for specific styles within a CSS file, you can use the :global scope. For example:

.header {
background-color: red;
}

:global .global-header {
background-color: blue;
}

In this example, the .header class will be processed as a CSS Module, while the .global-header class will not be processed as a module and will have a global scope.

To disable CSS Modules processing for specific files, such as global styles, you can add the cssModulePattern regular expression to the configuration as follows:

{
"postcss": {
// CSS Modules processing will be skipped for *.global.css files
"cssModulePattern": "^(?!.*global\\.css$).*$"
}
}

Typings

For prevent typescript issues with import .css files, make sure that your custom types declaration contains @tramvai/cli package reference:

typings.d.ts
/// <reference types="@tramvai/cli" />

PostCSS

tramvai provides complete PostCSS integration. Default path for file with PostCSS plugins is postcss.config.js, and is defined by the parameter postcss.config in tramvai.json:

tramvai.json
{
"projects": {
"appName": {
"postcss": {
"config": "src/postcss"
}
}
}
}

Recommended list of plugins are already included for new tramvai applications, and default configuration looks like this:

src/postcss.js
module.exports = {
plugins: [
require('postcss-nested'),
require('postcss-modules-values-replace'),
require('postcss-custom-properties')({
preserve: false,
}),
require('postcss-custom-media')({
preserve: false,
}),
],
};

Third-party styles

For example, we want to include antd styles - antd/dist/antd.css. We have a few options for this - direct import in CSS file, or with DI provider.

Local import

⌛ First, install postcss-global-import plugin:

npm install --save-dev postcss-global-import

⌛ Add plugin to application:

src/postcss.js
module.exports = {
plugins: [
require('postcss-nested'),
require('postcss-modules-values-replace'),
require('postcss-custom-properties')({
preserve: false,
}),
require('postcss-custom-media')({
preserve: false,
}),
require("postcss-global-import"),
],
};

⌛ Import file in any CSS module with @global-import directive:

antd.module.css
@global-import "antd/dist/antd.css";

⌛ And last, import this CSS module in the application:

index.ts
import './antd.module.css';

External import

With multi token RENDER_SLOTS you can easily add external styles to every application page:

index.ts
import { createApp, provide } from '@tramvai/core';
import { RENDER_SLOTS, ResourceType, ResourceSlot } from '@tramvai/module-render';

createApp({
name: 'appName',
modules: [],
providers: [
provide({
provide: RENDER_SLOTS,
useValue: {
type: ResourceType.style,
slot: ResourceSlot.HEAD_CORE_STYLES,
payload: 'https://cdnjs.cloudflare.com/ajax/libs/antd/4.24.5/antd.min.css',
},
}),
],
});

Performance

Class names

Library @tinkoff/minicss-class-generator used underhood for creation of short and unique class names. You can configure generator pattern with cssLocalIdentName option in tramvai.json.

Resource inlining

Any CSS files smaller than 40kb before gzip will be inlined in HTML markup. You can configure automatic resource inlining with provider RESOURCE_INLINE_OPTIONS.