discourse-writing-html-css

Write and repair HTML, CSS, and SCSS for Discourse core, plugins, themes, and theme components.

47.8k|9.0k|Updated Jan 12, 2013
One-click install
npx skills add https://github.com/discourse/discourse --skill discourse-writing-html-css
Or copy as Structured Prompt for Agent
Please help me install this Agent Skill.
Skill: discourse-writing-html-css
Source: https://github.com/discourse/discourse/tree/main/.skills/discourse-writing-html-css
Command: npx skills add https://github.com/discourse/discourse --skill discourse-writing-html-css

SYSTEM DOCUMENTATION & REQUIREMENTS

💡 This Skill includes references (resource) components.

What problem does it solve?

Discourse UI code must survive themes, light and dark color schemes, every viewport width, and screen readers, and ad-hoc styling breaks under those conditions. This Skill encodes Discourse's frontend conventions so templates and stylesheets are themeable, responsive, and accessible by default.

Core Features & Use Cases

  • BEM naming with standalone modifiers: Enforces Discourse's modified BEM convention (block, block__element, standalone .--modifier, is-/has- state classes) so themes can target and override components cleanly.
  • Themeable color and theming rules: Prohibits hardcoded colors in favor of the CSS custom-property palette, semantic --token-color-* tokens, and --d-* design variables so dark mode and themes work without extra code.
  • CSS repair workflows: Provides patterns for fixing regressions—scoping broad selectors, deleting stale CSS, consolidating device splits into common/ with lib/viewport mixins, and fixing overflow with containment primitives.
  • Template and accessibility conventions: Covers .gjs/.hbs escaping, dIcon usage, FormKit forms, DButton variants, .sr-only text, a11y live-region announcements, and RTL logical properties.
  • Use Case: When fixing a mobile overflow bug in a plugin stylesheet, the Skill directs you to scope the leaking selector, replace fixed widths with minmax(0, 1fr) and min-width: 0, move the rule into common/ with viewport mixins, and verify across viewports, palettes, and RTL.

Quick Start

Use the discourse-writing-html-css skill to review my new component's .gjs template and SCSS file for BEM naming, hardcoded colors, and responsive layout issues.

Frequently Asked Questions about discourse-writing-html-css

High-intent search queries and answers about installing and using this skill.

FAQPage Schema
How do I name CSS classes in Discourse components?

Discourse uses a modified BEM convention: blocks like .chat-skeleton, elements like .chat-skeleton__message, and standalone modifier classes like .--cancel instead of block--modifier suffixes. State classes use is-/has- prefixes, and names should describe meaning rather than appearance, position, or color.

How do I make Discourse CSS work with themes and dark mode?

Never hardcode hex, rgb(), or named colors; use the CSS custom-property palette such as var(--primary), var(--secondary), and var(--tertiary), or semantic --token-color-* tokens. The palette inverts automatically per color scheme, so you should never write a separate dark-mode block.

Where should new stylesheets go in Discourse core and plugins?

New core styles belong in app/assets/stylesheets/common/ as one responsive stylesheet registered in the matching _index.scss, not in the legacy desktop/ or mobile/ directories. Plugin styles live in plugins/<name>/assets/stylesheets/ and are registered in plugin.rb with register_asset.

How do I fix a CSS regression or leaking selector in Discourse?

First check with rg whether the selector is still rendered, then prefer deleting stale CSS or scoping broad selectors to the real component or state rather than adding !important or deeper chains. Fix overflow with containment primitives like min-width: 0 and minmax(0, 1fr), and verify across viewports, palettes, RTL, and affected plugins.

Does Discourse still use separate mobile and desktop stylesheets?

No, the desktop/ and mobile/ directories, .mobile-view/.desktop-view classes, and site.mobileView are deprecated. New code uses one responsive stylesheet in common/ with the lib/viewport mixins (viewport.from/until/between) and prefers intrinsic layout like auto-fill grids over breakpoints.

When should I avoid using the .btn variant classes in Discourse?

Only controls that look and function like standard buttons get .btn plus exactly one variant such as btn-default, btn-primary, or btn-danger. Buttons inside dropdowns, menus, tabs, or list rows are styled by their own component class and must not receive .btn-* variants.