Styling

Rspeedy supports different ways of styling your application, including:

  • CSS Modules: Create locally scoped CSS classes to avoid naming conflicts and improve maintainability.

  • Global CSS: Simple to use and familiar for those experienced with traditional CSS, but can lead to larger CSS bundles and difficulty managing styles as the application grows.

  • CSS pre-processors: Popular CSS pre-processors like sass and less that extend CSS with features like variables, nested rules, and mixins.

  • PostCSS: A tool for transforming CSS.

Using CSS Modules

CSS Modules allows us to write CSS code in a modular way, and these styles can be imported and used in JavaScript files. Using CSS Modules can automatically generate unique class names, isolate styles between different modules, and avoid class name conflicts.

TIP

You can use Global CSS if you want some of the CSS to be non-isolated.

Rspeedy supports CSS Modules by default, you don't need to add additional configuration. Our convention is to use the [name].module.css filename to enable CSS Modules.

Example

  1. Write styles as usual:
button.module.css
.red {
  background: red;
}
  1. Use styles like a module:
Button.jsx
import styles from './button.module.css';

export function Button() {
  return (
    <view className={styles.red}>
      <text>Button</text>
    </view>
  );
}

Or, you can use Named Imports:

Button.jsx
import { red } from './button.module.css';

export function Button() {
  return (
    <view className={red}>
      <text>Button</text>
    </view>
  );
}

With CSS Pre-Processor

The CSS Modules can also be used with CSS Pre-Processor. Just name your files with the pattern *.module.*.

E.g.: the following style files are considered CSS Modules:

  • *.module.css
  • *.module.less
  • *.module.sass
  • *.module.scss
  • *.module.styl
  • *.module.stylus

Recognition Rules

By default, only files ending with *.module.{css,scss,less} are recognized as CSS Modules.

If you want to treat other CSS files as CSS Modules as well, you can achieve this by configuring output.cssModules.auto.

For example:

lynx.config.ts
import { defineConfig } from '@lynx-js/rspeedy';

export default defineConfig({
  output: {
    cssModules: {
      auto(filename) {
        return filename.includes('.module.') || filename.includes('/shared/');
      },
    },
  },
});

Given this configuration, the following imports will be recognized as CSS Modules:

import * as foo from './foo.module.css';
import * as bar from './shared/bar.css';

Type Declaration

When you import CSS Modules in TypeScript code, TypeScript may prompt that the module is missing a type definition:

TS2307: Cannot find module './index.module.css' or its corresponding type declarations.

To fix this, you need to add a type declaration file for the CSS Modules, please create a src/rspeedy-env.d.ts file, and add the corresponding type declaration.

src/rspeedy-env.d.ts
/// <reference types="@lynx-js/rspeedy/client" />
TIP

create-rspeedy will automatically create this file for you.

If type errors still exist after adding the type declaration, you can try to restart the current IDE. Making sure the TypeScript can correctly identify the type definition.

Generate exact type declaration

The @lynx-js/rspeedy/client will give type declarations like this:

declare module '*.module.css' {
  type CSSModuleClasses = {
    readonly [key: string]: string;
  };
  const classes: CSSModuleClasses;
  export default classes;
}

Using Typed CSS Modules Plugin with Rspeedy will generate type declaration files for all CSS Modules with exact type declarations.

  1. Install the @rsbuild/plugin-typed-css-modules package
npm
yarn
pnpm
bun
npm add -D @rsbuild/plugin-typed-css-modules
  1. Add the pluginTypedCSSModules to lynx.config.ts
lynx.config.ts
import { pluginTypedCSSModules } from '@rsbuild/plugin-typed-css-modules';

import { pluginReactLynx } from '@lynx-js/react-rsbuild-plugin';
import { defineConfig } from '@lynx-js/rspeedy';

export default defineConfig({
  source: {
    entry: './src/index.tsx',
  },
  plugins: [pluginReactLynx(), pluginTypedCSSModules()],
});

After running rspeedy build or rspeedy dev, the type declarations will be generated.

button.module.css.d.ts
// This file is automatically generated.
// Please do not change this file!
interface CssExports {
  red: string;
}
export const cssExports: CssExports;
export default cssExports;

You may also need to add "allowArbitraryExtensions": true and "moduleResolution": "Bundler" to tsconfig.json.

tsconfig.json
{
  "compilerOptions": {
    "module": "ESNext",
    "moduleResolution": "Bundler",
    "allowArbitraryExtensions": true
  }
}

Using Global CSS

In some case, you may want the CSS styles to be used with some complex selector. It is called Global CSS in ReactLynx.

Just write CSS code and imported from a javascript file.

Example

  1. Write styles as usual:
styles.css
.red {
  background: red;
}

.red > text {
  color: blue;
}
  1. Import the .css file from the JSX file and use the CSS classes:
index.jsx
import './styles.css';

export default function App() {
  return (
    <view className="red">
      <text>Hello, Rspeedy!</text>
    </view>
  );
}

Using CSS Pre-Processors

CSS pre-processors extend CSS with features like variables, nested rules, and mixins.

Using sass

  1. Install the @rsbuild/plugin-sass package
npm
yarn
pnpm
bun
npm install -D @rsbuild/plugin-sass
  1. Add the pluginSass to lynx.config.ts
lynx.config.ts
import { pluginSass } from '@rsbuild/plugin-sass';

import { defineConfig } from '@lynx-js/rspeedy';

export default defineConfig({
  source: {
    entry: './src/index.tsx',
  },
  plugins: [
    pluginSass({
      /** sass options */
    }),
  ],
});

Then simply create .scss or .sass files and import them into JavaScript.

import './global.sass';
import styles from './button.module.scss';

export function App() {
  return (
    <view className={styles.red}>
      <text className="title">Hello, Sass</text>
    </view>
  );
}

More options can be used in pluginSass, please refer to Sass Plugin for usage.

Using less

  1. Install the @rsbuild/plugin-less package
npm
yarn
pnpm
bun
npm install -D @rsbuild/plugin-less
  1. Add the pluginLess to lynx.config.ts
lynx.config.ts
import { pluginLess } from '@rsbuild/plugin-less';

import { defineConfig } from '@lynx-js/rspeedy';

export default defineConfig({
  source: {
    entry: './src/index.tsx',
  },
  plugins: [
    pluginLess({
      /** less options */
    }),
  ],
});

Then simply create .less files and import them into JavaScript.

import './global.less';
import styles from './button.module.less';

export function App() {
  return (
    <view className={styles.red}>
      <text className="title">Hello, Less</text>
    </view>
  );
}

More options can be used in pluginLess, please refer to Less Plugin for usage.

Using stylus

  1. Install the @rsbuild/plugin-stylus package
npm
yarn
pnpm
bun
npm install -D @rsbuild/plugin-stylus
  1. Add the pluginStylus to lynx.config.ts
lynx.config.ts
import { pluginStylus } from '@rsbuild/plugin-stylus';

import { defineConfig } from '@lynx-js/rspeedy';

export default defineConfig({
  source: {
    entry: './src/index.tsx',
  },
  plugins: [
    pluginStylus({
      /** stylus options */
    }),
  ],
});

More options can be used in pluginStylus, please refer to Stylus Plugin for usage.

Using PostCSS

Powered by Rsbuild, Rspeedy has built-in PostCSS to transform the CSS code.

Rsbuild uses postcss-load-config to load the PostCSS configuration file in the root directory of the current project, such as postcss.config.js:

export default {
  plugins: {
    'postcss-px-to-viewport': {
      viewportWidth: 375,
    },
  },
};
Except as otherwise noted, this work is licensed under a Creative Commons Attribution 4.0 International License, and code samples are licensed under the Apache License 2.0.