Zum Inhalt springen

css-Helfer ​

Der CSS-Helfer hono/css ist Honos integrierte Lösung für CSS in JS(X).

Du kannst CSS in JSX in einem JavaScript-Template-Literal namens css schreiben. Der Rückgabewert von css ist der Klassenname, den du als Wert des class-Attributs setzt. Die Komponente <Style /> enthält anschließend den CSS-Inhalt.

Import ​

ts
import { Hono } from 'hono'
import { css, cx, keyframes, Style, createCssContext } from 'hono/css'

css Experimental ​

Du kannst CSS im Template-Literal css schreiben. In diesem Beispiel dient headerClass als Wert des Attributs class. Vergiss nicht, <Style /> hinzuzufügen, da diese Komponente den CSS-Inhalt enthält.

ts
app.get('/', (c) => {
  const headerClass = css`
    background-color: orange;
    color: white;
    padding: 1rem;
  `
  return c.html(
    <html>
      <head>
        <Style />
      </head>
      <body>
        <h1 class={headerClass}>Hello!</h1>
      </body>
    </html>
  )
})

Mit dem Verschachtelungsselektor & kannst du Pseudoklassen wie :hover gestalten:

ts
const buttonClass = css`
  background-color: #fff;
  &:hover {
    background-color: red;
  }
`

Erweitern ​

Du kannst die CSS-Definition erweitern, indem du den Klassennamen einbettest.

tsx
const baseClass = css`
  color: white;
  background-color: blue;
`

const header1Class = css`
  ${baseClass}
  font-size: 3rem;
`

const header2Class = css`
  ${baseClass}
  font-size: 2rem;
`

Außerdem ermöglicht die Syntax ${baseClass} {} das Verschachteln von Klassen.

tsx
const headerClass = css`
  color: white;
  background-color: blue;
`
const containerClass = css`
  ${headerClass} {
    h1 {
      font-size: 3rem;
    }
  }
`
return c.render(
  <div class={containerClass}>
    <header class={headerClass}>
      <h1>Hello!</h1>
    </header>
  </div>
)

Globale Styles ​

Mit einem Pseudoselektor namens :-hono-global kannst du globale Styles definieren.

tsx
const globalClass = css`
  :-hono-global {
    html {
      font-family: Arial, Helvetica, sans-serif;
    }
  }
`

return c.render(
  <div class={globalClass}>
    <h1>Hello!</h1>
    <p>Today is a good day.</p>
  </div>
)

Alternativ kannst du CSS mit dem Literal css in der Komponente <Style /> schreiben.

tsx
export const renderer = jsxRenderer(({ children, title }) => {
  return (
    <html>
      <head>
        <Style>{css`
          html {
            font-family: Arial, Helvetica, sans-serif;
          }
        `}</Style>
        <title>{title}</title>
      </head>
      <body>
        <div>{children}</div>
      </body>
    </html>
  )
})

keyframes Experimental ​

Mit keyframes kannst du den Inhalt von @keyframes schreiben. In diesem Beispiel ist fadeInAnimation der Name der Animation.

tsx
const fadeInAnimation = keyframes`
  from {
    opacity: 0;
  }
  to {
    opacity: 1;
  }
`
const headerClass = css`
  animation-name: ${fadeInAnimation};
  animation-duration: 2s;
`
const Header = () => <a class={headerClass}>Hello!</a>

cx Experimental ​

cx kombiniert die beiden Klassennamen.

tsx
const buttonClass = css`
  border-radius: 10px;
`
const primaryClass = css`
  background: orange;
`
const Button = () => (
  <a class={cx(buttonClass, primaryClass)}>Click!</a>
)

Es kann auch einfache Zeichenfolgen kombinieren.

tsx
const Header = () => <a class={cx('h1', primaryClass)}>Hi</a>

Zusammen mit der Middleware Secure Headers verwenden ​

Wenn du die CSS-Helfer zusammen mit der Middleware Secure Headers verwenden möchtest, kannst du das Attribut nonce zu <Style nonce={c.get('secureHeadersNonce')} /> hinzufügen, um durch die CSS-Helfer verursachte Probleme mit der Content-Security-Policy zu vermeiden.

tsx
import { secureHeaders, NONCE } from 'hono/secure-headers'

app.get(
  '*',
  secureHeaders({
    contentSecurityPolicy: {
      // Set the pre-defined nonce value to `styleSrc`:
      styleSrc: [NONCE],
    },
  })
)

app.get('/', (c) => {
  const headerClass = css`
    background-color: orange;
    color: white;
    padding: 1rem;
  `
  return c.html(
    <html>
      <head>
        {/* Set the `nonce` attribute on the CSS helpers `style` and `script` elements */}
        <Style nonce={c.get('secureHeadersNonce')} />
      </head>
      <body>
        <h1 class={headerClass}>Hello!</h1>
      </body>
    </html>
  )
})

createCssContext Experimental ​

createCssContext erstellt CSS-Helferfunktionen (css, cx, keyframes, viewTransition, Style) mit einem eigenen Kontext. Damit kannst du die ID des Style-Elements und die erzeugten Klassennamen anpassen.

ts
import { createCssContext } from 'hono/css'

const { css, cx, keyframes, Style } = createCssContext({
  id: 'my-app',
})

classNameSlug ​

Standardmäßig werden CSS-Klassennamen im Format css-1234567890 erzeugt. Du kannst dies anpassen, indem du eine Funktion classNameSlug übergibst.

Die Funktion erhält drei Argumente:

  • hash - der standardmäßig erzeugte Klassenname, z. B. css-1234567890
  • label - aus einem /* comment */ am Anfang des CSS-Templates extrahiert; eine leere Zeichenfolge, wenn keiner vorhanden ist
  • css - die minifizierte CSS-Zeichenfolge
ts
const { css, Style } = createCssContext({
  id: 'my-styles',
  classNameSlug: (hash, label) => (label ? `h-${label}` : hash),
})

const heroClass = css`
  /* hero-section */
  background: blue;
`
// Generated class name: "h-hero-section"

onInvalidSlug ​

Wenn die Funktion classNameSlug einen ungültigen CSS-Klassennamen zurückgibt, wird standardmäßig eine Warnung protokolliert. Mit onInvalidSlug kannst du dieses Verhalten anpassen.

ts
const { css, Style } = createCssContext({
  id: 'my-styles',
  classNameSlug: (hash, label) => label || hash,
  onInvalidSlug: (slug) => {
    throw new Error(`Invalid CSS class name: ${slug}`)
  },
})

Sicherheit ​

Die CSS-Helfer sind APIs zum Verfassen von CSS: Wie bei anderen CSS-in-JS-Bibliotheken werden interpolierte Werte als unverarbeitetes CSS eingefügt. Sie verhindern das Ausbrechen in HTML durch Anführungszeichen, Backslashes und </. {, } und ; werden jedoch durchgelassen, da sie gültiges CSS sind.

Achtung

Behandle die CSS-Helfer wie andere Schnittstellen für unverarbeitete Ausgabe (html, raw, rawCssString): Übergib ihnen keine nicht vertrauenswürdigen Eingaben direkt. Das ermöglicht CSS-Injection. Prüfe die Werte zuerst anhand einer Positivliste.

tsx
const ALLOWED_COLORS = ['red', 'green', 'blue']
const color = ALLOWED_COLORS.includes(input) ? input : 'black'
const headerClass = css`
  color: ${color};
`

Tipps ​

Wenn du VS Code verwendest, kannst du mit vscode-styled-components Syntaxhervorhebung und IntelliSense für CSS-Template-Literale mit Tags nutzen.

Veröffentlicht unter der MIT-Lizenz.