Jesse A. Green / notebook

Semantic UI — Administrator & Architecture Guide

Generated June 2026 from Semantic-Org/Semantic-UI at 597843a

AI-generated documentation. The library is checked by sampling (three repositories so far); this guide was not individually reviewed. Verify against the project before relying on it.

This guide is the technical reference for engineers, architects, and maintainers who integrate, build, customize, secure, or contribute to Semantic UI. Where the User Guide covers how to use the framework, this guide covers how it is built — the LESS theming pipeline, the JavaScript module architecture, the Gulp build system, the configuration surface, security considerations, and the contribution workflow. It is written against Semantic UI 2.5.0 (source commit 597843a).


Table of Contents

  1. Executive Summary
  2. Architecture
  3. Requirements
  4. The Build System
  5. Configuration Reference
  6. Customization Deep Dive (Theming)
  7. The JavaScript Module Architecture
  8. Security
  9. Testing Strategy
  10. Operations & Performance
  11. Component Internals Reference
  12. Troubleshooting & Known Issues
  13. Improvements & Technical Debt
  14. Contributing
  15. Quick Reference

1. Executive Summary

Semantic UI is a CSS-first front-end framework whose value proposition is theming. It is built around three architectural pillars:

  1. A LESS source tree organized by a five-category component taxonomy (Globals, Elements, Collections, Views, Modules). Roughly 50+ components are authored as LESS, exposing ~3000 CSS variables for customization.
  2. A three-level theme-inheritance model (default theme → packaged theme → site theme) wired together with LESS @import (optional) directives, selected per-component via a theme.config file. This is the framework's distinguishing design and the reason its README calls it "a UI framework designed for theming."
  3. A jQuery-based JavaScript layer of 16 interactive Modules and 3 Behaviors, all following a uniform plugin pattern (initialize → invoke-behavior-by-string → settings object with callbacks and debug instrumentation).

The repository ships precompiled output in dist/ (combined and per-component CSS/JS) plus a Gulp 4 build system that compiles a developer's themed LESS into a customized bundle. An interactive installer scaffolds project configuration on first npm install.

Attribute Value
Version 2.5.0 (released Oct 6, 2022)
License MIT
Source language LESS (styles) + ES5 JavaScript / jQuery (modules)
Runtime dependency jQuery ^3.5.1 (for Modules/Behaviors only)
Build system Gulp 4 + LESS + autoprefixer + clean-css + uglify
Component count 16 Elements + 6 Collections + 6 Views + 16 Modules + 3 Behaviors + 2 Globals
Packaged themes 23
Total source ~526 files, ~320K source chars

Note

Semantic UI is the upstream "vanilla" framework. Several official sibling distributions are maintained as separate repositories: semantic-ui-css (precompiled), semantic-ui-less (LESS only), and framework integrations for React, Angular, Ember, and Meteor. Architectural decisions here (notably the jQuery dependency) explain why those wrappers exist.


2. Architecture

2.1 High-level structure

                          ┌──────────────────────────────────────┐
                          │         src/  (authored source)       │
                          ├──────────────────────────────────────┤
   theme.config  ───────► │  definitions/   LESS + JS per         │
   (per-component theme   │    ├── globals/      component        │
    selection)            │    ├── elements/                      │
                          │    ├── collections/                   │
   site/  ──────────────► │    ├── views/                         │
   (your overrides)       │    ├── modules/   (LESS + .js)        │
                          │    └── behaviors/ (.js only)          │
   themes/  ────────────► │  themes/        23 packaged themes    │
   (default + packaged)   │    └── <theme>/<type>s/<comp>.variables
                          │                          + .overrides │
                          └───────────────┬──────────────────────┘
                                          │  gulp build
                       ┌──────────────────▼───────────────────┐
                       │   LESS compile → autoprefix →         │
                       │   concat → clean-css → uglify         │
                       └──────────────────┬───────────────────┘
                                          ▼
                       ┌──────────────────────────────────────┐
                       │   dist/                               │
                       │     semantic.css / .min.css           │
                       │     semantic.js  / .min.js            │
                       │     components/<comp>.css|js (+min)    │
                       │     themes/   (fonts + image assets)   │
                       └──────────────────────────────────────┘

2.2 The component taxonomy

The five categories are not cosmetic — they determine whether a component has JavaScript and where its files live.

Category Has LESS Has JS Semantics
Globals (reset, site) Yes site only Page-wide reset + global site variables
Elements (16) Yes No Atomic building blocks (button, icon, input…)
Collections (6) Yes No Groups of elements (form, grid, menu, table…)
Views (6) Yes No Content presentations (card, feed, comment…)
Modules (16) Yes Yes Interactive widgets (dropdown, modal, popup…)
Behaviors (3) No Yes JS-only helpers (api, form, visibility)

This split is load-bearing for the build: CSS-only categories compile to stylesheet output only, while Modules emit both a .css and a .js in dist/components/, and Behaviors emit .js only.

2.3 The LESS import cascade

The heart of the theming architecture is src/theme.less, which every component imports. For a given component it resolves variables and overrides by importing up to four layers in priority order:

/* Site (global) variables — default → packaged → component-theme → site */
@import "@{themesFolder}/default/globals/site.variables";
@import (optional) "@{themesFolder}/@{site}/globals/site.variables";
@import (optional) "@{themesFolder}/@{theme}/globals/site.variables";
@import (optional) "@{siteFolder}/globals/site.variables";

/* Component variables — default → packaged theme → site theme */
@import "@{themesFolder}/default/@{type}s/@{element}.variables";
@import (optional) "@{themesFolder}/@{theme}/@{type}s/@{element}.variables";
@import (optional) "@{siteFolder}/@{type}s/@{element}.variables";

/* Component overrides (custom rules) — packaged theme → site theme */
.loadUIOverrides() {
  @import (optional) "@{themesFolder}/@{theme}/@{type}s/@{element}.overrides";
  @import (optional) "@{siteFolder}/@{type}s/@{element}.overrides";
}

The @theme variable is resolved dynamically per component: @theme: @@element; reads the value of the per-component theme variable defined in theme.config (e.g. @button: 'github' makes @theme equal 'github' while compiling the button). @import (optional) means a layer is silently skipped if that theme doesn't define the file — which is why a packaged theme only needs to ship the components it actually restyles.

Important

This cascade is the single most important architectural fact in the codebase. Variables flow default → packaged → site with later winning; .overrides files add raw CSS rules with access to all resolved variables. A maintainer reading or extending the theme system must understand theme.less before anything else.

2.4 The JavaScript module pattern

Every Module and Behavior is an IIFE that registers a jQuery plugin and follows an identical skeleton (illustrated with dropdown):

(function ($, window, document) {
  $.fn.dropdown = function (parameters) {
    // for each matched element:
    //   - read merged settings (defaults ← $.fn.dropdown.settings ← call args ← data-* attrs)
    //   - build a `module` object with all methods
    //   - module.initialize() binds events, caches DOM
    //   - module.invoke(query) dispatches string method calls
    //   - instance stored via $.data(element, moduleNamespace)
  };
  $.fn.dropdown.settings = { /* defaults, callbacks, selectors, className, error, metadata */ };
})(jQuery, window, document);

Key shared sub-objects inside every settings:

Sub-object Role
(top-level keys) Behavioral defaults (on, transition, duration, …)
on* callbacks Lifecycle hooks the integrator overrides
selector CSS selectors the module uses to find sub-parts
className State class names the module toggles (active, visible, …)
metadata data-* attribute names the module reads/writes
error Human-readable error strings (logged on misuse)
regExp / text / message Module-specific lookups and user-facing strings

The invoke dispatcher is what makes $('.ui.modal').modal('show') work: the string 'show' is resolved against the module object's methods. This pattern is uniform across all 19 JS files, so understanding one module's structure transfers to all of them.


3. Requirements

Concern Requirement Notes
Runtime (browser) jQuery 3.x (^3.5.1) Required only for Modules + Behaviors. CSS components need nothing.
Build (Node) Node.js 18+ 2.5.0 updated scripts to build under Node 18.
Build (Gulp) Gulp 4 All tasks rewritten for Gulp 4 in 2.5.0 (was Gulp 3).
Build (LESS) bundled via gulp-less Source contains no vendor prefixes; autoprefixer runs in the build.
Browser targets Last 2 FF/Chrome/Safari(Mac), IE 11+, Edge 12+, Android 4.4+, iOS Safari 7+ Flexbox components (grid) unsupported on IE9.

Build-tool dependencies

The package.json declares a Gulp-centric toolchain (also mirrored in peerDependencies):

Dependency Role
gulp, gulp-less Task runner + LESS compilation
gulp-autoprefixer Adds vendor prefixes (source has none)
gulp-clean-css CSS minification
gulp-uglify JS minification
gulp-concat, gulp-concat-css, gulp-rename, gulp-flatten, gulp-copy File assembly
gulp-rtlcss RTL stylesheet generation
gulp-header License banner injection
yamljs Reads YAML build config
jquery ^3.5.1 Runtime dependency vendored for tests/dist

Note

Skipping a dependency-documentation lookup for these is intentional: they are well-known build tools, and the framework's own source is the authoritative description of how it uses them. The interesting integration is the theme.less cascade and the Gulp task graph, not the individual plugins' APIs.


4. The Build System

4.1 Gulp task graph

gulpfile.js wires the tasks defined under tasks/:

Task Source Purpose
build tasks/build.js Full build: CSS + JS + assets
build-css tasks/build/css.js LESS → autoprefix → concat → minify → dist/
build-javascript tasks/build/javascript.js Concatenate + uglify module JS → dist/
build-assets tasks/build/assets.js Copy fonts + images to dist/themes/
watch tasks/watch.js Incremental rebuild on file change
clean tasks/clean.js Remove dist/
version tasks/version.js Print/stamp version
install tasks/install.js Interactive installer (see §4.3)
check-install tasks/check-install.js Default task — verifies setup, runs installer if unconfigured
build-rtl / watch-rtl tasks/rtl/ RTL builds (enabled when semantic.json.rtl is true)
serve-docs / build-docs tasks/docs/ Documentation site integration

The default Gulp task is check-install, so a bare gulp on an unconfigured project triggers the installer rather than failing.

4.2 Build output

A full build produces, in dist/:

  • semantic.css / semantic.min.css — every component, combined
  • semantic.js / semantic.min.js — every module, combined
  • components/<name>.css|js (+ .min) — per-component files for selective inclusion
  • themes/ — icon fonts and image assets referenced by the CSS

Tip

The per-component output in dist/components/ is the supported mechanism for shrinking payload: an integrator includes only the components their app uses instead of the full bundle. This is the framework's answer to tree-shaking, which LESS cannot do automatically.

4.3 The interactive installer

tasks/install.js runs a prompt-driven wizard (via the prompt-sui library). It:

  1. Detects an existing semantic.json and offers to extend or skip.
  2. Confirms the project root (or accepts a custom absolute path).
  3. Asks where to place Semantic UI inside the project.
  4. Offers three setup modes:
    • Automatic — default locations, all components.
    • Express — choose components + output folder.
    • Custom — customize all src/dist paths.
  5. Presents a component checkbox list for selective installs.
  6. Writes semantic.json, theme.config, and the site/ folder from their .example/_site templates.

Note

The installer is what renames theme.config.example → theme.config and _site/ → site/. For manual installs (no installer), these renames must be done by hand, as documented in src/README.md.


5. Configuration Reference

There are three configuration artifacts. They control what theme each component uses, where build files live, and the values inside each theme.

5.1 theme.config — per-component theme selection

A LESS file (from theme.config.example) assigning a theme name to every component, grouped by category, plus folder paths:

/* Global */    @site: 'default';  @reset: 'default';
/* Elements */  @button: 'default'; @input: 'default'; …
/* Modules */   @dropdown: 'default'; @modal: 'default'; …
/* Folders */
@themesFolder : 'themes';   /* path to packaged themes */
@siteFolder   : 'site';     /* path to YOUR overrides  */
@import (multiple) "theme.less";

To restyle a component, set its variable to any theme name present in src/themes/ (e.g. @button: 'material';). All 50+ component variables plus @themesFolder and @siteFolder are configurable here.

5.2 semantic.json — build paths and flags

A JSON file (from semantic.json.example) read by the build tools:

Key Default Purpose
base "" Base path prepended to all paths
paths.source.config src/theme.config Where the theme config lives
paths.source.definitions src/definitions/ Component LESS+JS
paths.source.site src/site/ Site overrides
paths.source.themes src/themes/ Packaged themes
paths.output.packaged dist/ Combined bundle output
paths.output.uncompressed dist/components/ Per-component, unminified
paths.output.compressed dist/components/ Per-component, minified
paths.output.themes dist/themes/ Asset output
paths.clean dist/ Directory cleaned by gulp clean
permission false File permission (chmod) to apply to output
autoInstall false Re-run install automatically
rtl false Enable RTL build tasks (true, false, or 'both')

5.3 Global LESS variables (site.variables)

The most-changed global variables live in themes/default/globals/site.variables. Override them in site/globals/site.variables:

Variable Default Controls
@emSize 14px The base size; everything scales from it
@fontSize 14px Body text size
@fontName 'Lato' Primary font family
@headerFont / @pageFont Lato stack Header / body font stacks
@importGoogleFonts true Whether to fetch the font from Google Fonts at runtime
@googleFontRequest derived The exact Google Fonts URL query
@primaryColor @blue Primary brand color
@secondaryColor @black Secondary brand color
@bold / @normal bold / normal Font weights
@defaultBorderRadius @absoluteBorderRadius (4px) Corner rounding baseline
@h1–@h5 rem ratios Heading sizes

Each component additionally has its own <component>.variables file (e.g. elements/button.variables exposes @backgroundColor, @verticalPadding, @horizontalPadding, @borderRadius, shadow variables, and more). With ~3000 variables across the framework, the per-component variable file is that component's configuration reference — inspect themes/default/<type>s/<component>.variables to see every knob.

5.4 JavaScript module settings

Each Module/Behavior exposes $.fn.<module>.settings. All share a common instrumentation core:

Setting Default Purpose
silent false Suppress all console output
debug false Log internal events
verbose false Verbose internal logging
performance true Emit a performance trace
name (module) Name shown in logs
namespace (module) Event/data namespace

Module-specific keys, callbacks, selectors, className maps, metadata maps, and error strings are defined alongside these. The complete callback inventory per module is in §11.


6. Customization Deep Dive (Theming)

There are three layers of customization, in increasing specificity. A maintainer should steer integrators toward the highest-numbered layer that solves their problem.

Layer 1 — Pick a packaged theme (theme.config)

Cheapest customization: set a component to one of the 23 shipped themes.

@button : 'github';
@menu   : 'material';

Layer 2 — Override variables (site/**/<component>.variables)

Change values without writing CSS. The site theme is always the last @import in the cascade, so it wins.

/* site/globals/site.variables */
@primaryColor : @teal;
@fontName     : 'Inter';
@emSize       : 16px;

/* site/elements/button.variables */
@borderRadius : 0;

Layer 3 — Custom CSS (site/**/<component>.overrides)

For rules no variable exposes. .overrides files are imported after variables and have access to all of them.

/* site/elements/button.overrides */
.ui.button.brand {
  background: linear-gradient(@primaryColor, darken(@primaryColor, 10%));
}

Caution

Do not customize by writing !important overrides against compiled semantic.css. That fights the cascade, breaks on upgrade, and discards the entire theming system. The supported path is variables → overrides → rebuild.

Color system

Named colors (@blue, @red, @green, @teal, …) and @primaryColor/@secondaryColor are defined once and consumed everywhere. Overriding @primaryColor re-skins primary buttons, active menu items, focused inputs, progress bars, and more in one change — the framework's "shared vocabulary" applied to color.


7. The JavaScript Module Architecture

7.1 Settings resolution order

When $('.ui.x').x(opts) runs, settings are merged from (lowest to highest priority):

  1. $.fn.x.settings (framework defaults)
  2. A global override of $.fn.x.settings (set once at app start)
  3. The opts object passed at the call site
  4. data-* attributes on the element (per the module's metadata/attribute parsing)

7.2 Instance lifecycle

  • initialize — caches DOM (module.refresh), binds namespaced events, optionally fires init callbacks (fireOnInit).
  • invoke — the string-dispatch entry point; x('method', args) resolves method against the instance.
  • setting — read/write any setting at runtime (x('setting', 'debug', true)).
  • destroy — unbinds all namespaced events and clears $.data, leaving the DOM intact.

Because events are bound under a per-instance namespace, multiple instances and clean teardown are race-free — destroy removes exactly that instance's handlers.

7.3 Inter-module dependencies

Module Depends on
dropdown, modal, dimmer, popup, sidebar, etc. transition (for show/hide animations) — emits the noTransition error if absent
modal dimmer (creates the backdrop)
dropdown (remote), search, tab (remote) api behavior (AJAX)

Important

When building a custom per-component JS bundle, you must include the transitive dependencies. A dropdown.js without transition.js throws This module requires ui transitions at runtime. The safest minimal set for any animated module is { component, transition }, plus { dimmer } for modal and { api } for remote data.


8. Security

Semantic UI is primarily CSS, but its JavaScript layer renders HTML and makes network requests, which creates a real (if narrow) security surface. Treat the items below as a checklist for any app embedding user-generated content.

8.1 HTML rendering / XSS

Several modules render content that can be HTML:

  • Dropdown has preserveHTML: true by default — selected values, labels, and menu text are inserted as HTML, not escaped.
  • Popup content (data-content / content / html) is rendered into the popup.
  • Search renders result templates.

Caution

If any of these render user-supplied or server-reflected strings, set preserveHTML: false (dropdown, popup, search) so values are escaped, or sanitize the input server-side before it reaches the DOM. The framework does not ship an HTML sanitizer of its own; escaping is the integrator's responsibility. This is the most important security control for Semantic UI apps.

8.2 The api behavior

The api behavior builds request URLs from templates with {name} placeholders filled from urlData and element data-* attributes. Risks and mitigations:

  • URL/template injection — never place untrusted values into url templates without encoding; prefer server-side allowlists of endpoints (the api map) over client-built URLs.
  • CSRF — api does not add CSRF tokens automatically; configure beforeXHR/headers to attach them.
  • Response handling — onSuccess receives the parsed response; do not .html() it unescaped.

8.3 Network/privacy: Google Fonts

By default (@importGoogleFonts: true), compiled CSS contains @import url(https://fonts.googleapis.com/...). This causes every visitor's browser to contact Google. For privacy regimes (GDPR), strict CSP, or offline deployments:

  • Set @importGoogleFonts: false and self-host the font.
  • Or pin a CSP font-src/style-src that permits the Google domains intentionally.

(See also GitHub #7146, where the Google requests surfaced as runtime errors.)

8.4 Dependency posture

  • The runtime dependency is jQuery ^3.5.1. Track jQuery security advisories and pin a patched 3.x in your own app; the framework's floor is 3.5.1.
  • An open security report exists upstream (GitHub #7154, "Open vulnerability flagged by security team"). Maintainers and adopters should monitor it. Consistent with responsible disclosure, specifics are not reproduced here; review the upstream issue and apply any published guidance.

Warning

Because development cadence has slowed (see §13), do not assume timely upstream security patches. For long-lived deployments, budget for self-maintaining the dependency tree or evaluate an actively maintained community fork.


9. Testing Strategy

9.1 Framework

Tests run under Karma + Jasmine (karma.conf.js). The harness loads jQuery, the compiled CSS (from docs/build), all module source from src/definitions/**/*.js, shared helpers from test/helpers/, HTML fixtures from test/fixtures/, and the specs.

9.2 Coverage

Specs exist for the interactive modules where behavior is most testable:

test/modules/
  accordion.spec.js   checkbox.spec.js   dropdown.spec.js
  modal.spec.js       popup.spec.js      search.spec.js
  shape.spec.js       sidebar.spec.js    tab.spec.js
  module.spec.js      (shared module-contract tests)

Note

Coverage is concentrated on Modules (the JS surface). Pure-CSS Elements/Collections/Views are validated visually via the examples/ HTML pages rather than by unit tests — a reasonable strategy for a CSS framework, but it means stylesheet regressions are caught by eye, not by CI assertion. There is a test/meteor/ suite for the Meteor integration and a test/coverage/ output directory.

9.3 Visual/manual testing

The examples/ directory (grid.html, responsive.html, sticky.html, theming.html, login.html, etc.) doubles as a manual test surface. The src/README.md recommends running gulp watch, editing theme files, and refreshing an example page to inspect theme changes.


10. Operations & Performance

10.1 Payload management

Lever Effect
Use dist/components/* selectively Ship only components in use — the primary size lever
Minified bundles (*.min.css/js) Production default
Drop unused themes Don't ship dist/themes/<unused> assets
Self-host / subset the icon font The icon font is a notable fixed cost
Disable Google Fonts import Removes a runtime network round-trip

Tip

The full semantic.min.css contains all ~50 components plus the icon font. Most applications use a fraction; the per-component build is how you avoid shipping the rest. There is no automatic dead-CSS elimination in the LESS pipeline.

10.2 Build performance

  • gulp watch does incremental compilation — only the touched component and its dependents rebuild.
  • A full gulp build recompiles every component's four-layer LESS cascade; on large custom theme sets this is the slow path. Run it for releases, not on every edit.

10.3 Caching & CDN

dist/ output is fully static. Serve with long-lived cache headers and fingerprinted filenames. The CDN distributions (cdnjs / jsDelivr) are appropriate for the default theme.


11. Component Internals Reference

11.1 Module callback inventory

Module Callbacks
accordion onOpen, onOpening, onClose, onClosing, onChange, onChanging
checkbox onChange, onChecked, onUnchecked, onIndeterminate, onDeterminate, onEnable, onEnabled, onDisable, onDisabled
dimmer onShow, onHide, onChange, onStart, onComplete
dropdown onChange, onAdd, onRemove, onLabelSelect, onLabelCreate, onLabelRemove, onNoResults, onShow, onHide
embed onCreate, onDisplay, onPlaceholderDisplay, onEmbed, onPlay, onPause, onStop, onReset
modal onShow, onVisible, onHide, onHidden, onApprove, onDeny, onStart, onComplete
nag (none — persistence via cookie/localStorage)
popup onCreate, onShow, onVisible, onHide, onHidden, onRemove, onUnplaceable
progress onChange, onSuccess, onWarning, onError, onActive, onNumeric, onLabelUpdate
rating onRate
search onSelect, onResults, onResultsAdd, onSearchQuery, onResultsOpen, onResultsClose, onSuccess, onError, onFailure, onAbort, onComplete, onText, onURL
shape onChange
sidebar onShow, onVisible, onHide, onHidden, onChange
sticky onStick, onUnstick, onTop, onBottom, onScroll, onReposition
tab onLoad, onFirstLoad, onRequest, onSuccess, onVisible
transition onStart, onShow, onHide, onComplete

11.2 Behavior callback inventory

Behavior Callbacks
api onRequest, onResponse, onSuccess, onComplete, onFailure, onError, onAbort
form onValid, onInvalid, onSuccess, onFailure
visibility onOnScreen, onOffScreen, onTopVisible/Reverse, onBottomVisible/Reverse, onPassing/Reverse, onPassed, onTopPassed/Reverse, onBottomPassed/Reverse, onFixed, onUnfixed, onLoad, onAllLoaded, onRefresh, onUpdate

11.3 Source layout

src/
  semantic.less              # imports every component (build-tool-free path)
  theme.less                 # the import cascade (default→packaged→site)
  theme.config(.example)     # per-component theme selection
  definitions/
    globals/{reset,site}.{less,js}
    elements/<16>.less
    collections/<6>.less
    views/<6>.less
    modules/<16>.{less,js}
    behaviors/{api,form,visibility}.js
  themes/<23 themes>/<type>s/<component>.{variables,overrides}
  _site/                     # template for the site theme (rename to site/)
tasks/                       # Gulp build, install, rtl, docs, admin
dist/                        # precompiled output (committed)
examples/                    # manual/visual test pages
test/                        # Karma+Jasmine specs, fixtures, helpers

12. Troubleshooting & Known Issues

Operational issues

Symptom Cause Resolution
$(...).modal is not a function jQuery missing or loaded after Semantic Load jQuery first; include the module's JS
Icons render as boxes Icon font not served at expected path Ship dist/themes/ assets; configure font loader/@fontPath
Module parse failed: Unexpected character '@' (#6771) Bundler importing CSS with no CSS loader Add css-loader/style-loader
This module requires ui transitions Animated module without transition Include transition.js
googleProtocol/googleFonts errors (#7146) Google Fonts import failing/blocked @importGoogleFonts: false + self-host
semantic-ui-css fails in CRA (#7073) Missing CSS/font loaders Use Semantic UI React, or configure loaders
Install fails (#7131, #7115) Old Node/Gulp 3 Node 18 + Gulp 4, or use semantic-ui-css

Confirmed upstream bugs (from the issue tracker)

Issue Component Summary
#5341 Modal Not working in some mobile browsers
#7153 Modal Page won't scroll after closing modal
#3236 Sidebar Doesn't toggle correctly in RTL build
#5670 Input Missing right border with action + error/focus
#7128 Segment Rendering bug
#5758 Dropdown Items not clickable on some iPhones
#7125 Dropdown Screen-reader (NVDA/JAWS) gaps in multiple-search-selection
#7154 Security Open vulnerability flagged (see §8.4)

Note

The framework's bug board uses a [Component] title convention and a Confirmed Bug label. Browsing the Confirmed Bug tag is the maintainers' recommended way to track known issues — useful when triaging whether a report is new.


13. Improvements & Technical Debt

These are observations from the source and issue tracker, framed as the maintenance backlog an adopter should weigh.

  • Maintenance cadence. The last release (2.5.0) is from October 2022 and primarily modernized the build for Node 18 / Gulp 4. The project's future has been discussed openly (issue #7108). Adopters of a new long-lived project should evaluate activity and actively maintained community forks before committing.
  • jQuery dependency. The interactive layer is tied to jQuery, which is increasingly out of step with modern component frameworks. This is the structural reason the official React/Angular/Vue ecosystems use separate wrapper repos. A web-components or framework-agnostic rewrite would be a major architectural shift.
  • ES5 JavaScript. Modules are pre-ES6 (var, function expressions, IIFE). Modernizing to ES modules would enable real tree-shaking, which the LESS-only build cannot provide today.
  • No automatic CSS dead-code elimination. Payload control is manual (per-component imports). A PurgeCSS-style step is left to integrators.
  • HTML escaping defaults. preserveHTML: true on dropdown is a foot-gun for user-content apps; a safer default (or a built-in sanitizer) would reduce XSS risk (§8.1).
  • Google Fonts on by default. The runtime Google dependency is a privacy/CSP liability that many teams must remember to disable (§8.3).
  • Test coverage is module-only. CSS components rely on visual inspection; there are no stylesheet regression assertions in CI.
  • RTL edge cases. Some components (e.g. sidebar, #3236) have known RTL defects; the RTL build is a generated transform, not hand-verified per component.

14. Contributing

The contribution workflow is defined in CONTRIBUTING.md:

  1. Usage questions go to Gitter / forums / StackOverflow — not GitHub Issues.
  2. Bug reports require a reproducible test case, ideally forked from the project's JSFiddle boilerplate. Bugs confirmed by a maintainer receive the Confirmed Bug label.
  3. Issue titles follow the [Component] Sub-type Should Do Correct Behavior convention in title case; enhancements use [Component] Add new feature.
  4. Pull requests target the next branch (not master/main).
  5. Framework-integration bugs (Ember/Meteor/Angular/React) should be filed against those projects' boards, not the core repo.

Build/dev loop for contributors

git clone https://github.com/Semantic-Org/Semantic-UI.git
cd Semantic-UI
npm install          # runs the installer; choose Automatic
gulp watch           # rebuild on change
# edit src/definitions/** or src/themes/**, refresh examples/*.html

Admin/release tasks live under tasks/admin/ and tasks/collections/admin.js and are enabled only when config.admin is set — these handle distribution repos (the semantic-ui-css, -less, component repos) and are not needed for normal contributions.


15. Quick Reference

Gulp commands

Command Purpose
gulp install Interactive setup wizard
gulp build Full CSS + JS + assets build
gulp build-css / build-javascript / build-assets Partial builds
gulp watch Rebuild on change
gulp clean Delete dist/
gulp build-rtl / watch-rtl RTL builds (needs rtl: true)
gulp version Version info

Configuration files

File From template Purpose
theme.config theme.config.example Per-component theme selection
semantic.json semantic.json.example Build paths + rtl/autoInstall/permission
site/ _site/ Your variable + override files

Customization layers (least → most specific)

  1. theme.config — pick a packaged theme per component
  2. site/**/*.variables — override variable values
  3. site/**/*.overrides — add custom CSS rules

JS API cheat sheet

$('.ui.x').x();                       // initialize
$('.ui.x').x({ setting: value });     // initialize with settings
$('.ui.x').x('behavior', arg);        // invoke a behavior
$('.ui.x').x('setting', 'k', v);      // set a setting at runtime
$('.ui.x').x('destroy');              // teardown

Component categories

Category Count JS?
Globals 2 site only
Elements 16 No
Collections 6 No
Views 6 No
Modules 16 Yes
Behaviors 3 Yes (JS-only)