Developers

Elements and typography

The classes shared between the templates and the components. Component views emit this markup and expect your template to style it, so these are the ones you cannot rename.

Why this is a contract and not a suggestion

A template is written once and then wraps markup written by other people, most of it years earlier. The only thing keeping those two halves compatible is this set of class names. com_bookings prints <div class="col span4"> and <p class="error"> without knowing which template will draw them; your template supplies the rules without knowing what will use them.

That gives you two jobs and one prohibition:

  • Style all of it. A template that never defines .aside leaves every component page without its sidebar. That failure is silent and looks like a bug in the component.
  • Restyle freely. Colours, spacing, type — none of that is fixed.
  • Do not rename any of it. There is no alias layer. Renaming .subject breaks every component at once.

When you write markup of your own — in a layout, or in an override — use these classes rather than inventing new ones, so a later template can restyle your page along with everything else.

The sources are in core/assets/less, with compiled equivalents in core/assets/css for anything not written in LESS:

Element LESS Compiled CSS
Grid grid.less columns.css
Buttons buttons.less buttons.css
Notifications notifications.less notifications.css
Pagination pagination.less pagination.css
Tabs tabs.less tabs.css
Layout layout.less layout.css

core/assets/less/site.less imports the whole set in the right order and is the shortest way to pick them all up.

The grid

Twelve fluid columns. A .grid wrapper, .col on each child, and a .span{n} saying how wide it is:

<div class="grid">
	<div class="col span3">…</div>
	<div class="col span3">…</div>
	<div class="col span3">…</div>
	<div class="col span3 omega">…</div>
</div>
  • Every column needs .col. That is what floats it and gives it the gutter.
  • The last column in a row needs .omega, which removes the trailing gutter. Without it the row overflows.
  • Columns are percentages of the container, so a grid nests inside a column of another grid with no extra work.
  • No clearing element is needed; .grid clears itself.

.span1 through .span12 exist, and .offset1 through .offset12 push a column to the right by that many columns:

<div class="grid">
	<div class="col span3 offset3">…</div>
	<div class="col span3">…</div>
	<div class="col span3 omega">…</div>
</div>

Fraction classes

Aliases for the common widths, easier to read than counting:

Class Equivalent Offset alias
.span-whole .span12 .offset-whole
.span-three-quarters .span9 .offset-three-quarters
.span-two-thirds .span8 .offset-two-thirds
.span-half .span6 .offset-half
.span-third .span4 .offset-third
.span-quarter .span3 .offset-quarter

Collapsing

grid.less rearranges rows as the viewport narrows. The rules count the columns in the row with :nth-last-child, so what happens depends on how many children the .grid has, not on their .span classes:

Breakpoint A row of six A row of four A row of three
@break6 — 1023px Three across, two rows
@break4 — 1000px Two across, two rows
@break3 — 900px Two across, three rows Two across Full width
@break2 — 500px Full width Full width Full width

Two escape hatches, both on the .grid:

  • .nobreak — never rearrange. Every rule above is written .grid:not(.nobreak).
  • .break6, .break4, .break3 — go straight to full-width columns at that breakpoint instead of rearranging.

The breakpoints are variables in core/assets/less/variables.less, so a LESS template can move them.

Sections and asides

Most component pages are a main column with a narrower one beside it. The markup is:

<section class="section">
	<div class="section-inner">
		<div class="aside">
			Secondary navigation, metadata, related items …
		</div>
		<div class="subject">
			The main content …
		</div>
	</div>
</section>

.aside must come before .subject in the source. The rules that size them are written .aside + .subject, so reversing the order leaves the layout broken. If that is a semantic problem for your page, use the grid instead.

Unlike the grid, .aside has a fixed width and .subject takes what is left.

Notifications

Five classes, all styled the same way and differing only in colour and the icon in the :before:

Class Meaning
.passed Success
.info Information
.help Help
.warning Warning
.error Error
<p class="passed">Your changes have been saved.</p>
<p class="error">That file is too large.</p>

The messages the application queues render through <jdoc:include type="message" /> as a definition list inside #system-message, and its dd elements pick up the same styling. Its dt elements are hidden by the stylesheet; they carry the message type for assistive technology, so do not remove them from the layout.

Hubzero.renderMessages() in core.js writes the same structure from JavaScript. See JavaScript.

Buttons

.btn on a link, a <button> or an <input type="submit">:

<a class="btn" href="#">Link</a>
<button class="btn">Button</button>
<input type="submit" class="btn" value="Submit" />

States

Class Effect
.active Pressed. :active gets the same styling
.disabled 65% opacity, cursor: not-allowed, pointer-events: none. The disabled attribute does the same

Variants

Class Effect
.btn-primary The emphasised action. One per form
.btn-secondary Smaller, not a colour change — this is the size modifier
.btn-success Green
.btn-info Blue
.btn-warning Orange
.btn-danger / .btn-error Red. The two are identical

Icons

Add any .icon-* class from Fontcons and the glyph is rendered in a tinted block at the left edge of the button, with the padding adjusted for it:

<a class="btn btn-danger icon-danger" href="#">Delete</a>
<a class="btn icon-prev" href="#">Previous</a>

Add .opposite to move the glyph to the right edge instead — what you want for a "next" control:

<a class="btn icon-next opposite" href="#">Next</a>

Groups

.btn-group joins buttons into one control, squaring off the inner corners:

<div class="btn-group">
	<a class="btn icon-prev" href="#">Previous</a>
	<a class="btn" href="#">All</a>
	<a class="btn icon-next opposite" href="#">Next</a>
</div>

Add .dropdown and a toggle for a menu:

<div class="btn-group dropdown">
	<a class="btn" href="#">Actions</a>
	<span class="btn dropdown-toggle"></span>
	<ul class="dropdown-menu">
		<li><a href="#">Edit</a></li>
		<li><a href="#">Duplicate</a></li>
		<li class="divider"></li>
		<li><a href="#">Delete</a></li>
	</ul>
</div>
  • .dropup instead of .dropdown opens the menu upwards.
  • .btn-group.btn-secondary makes the whole group the smaller size.
  • .divider on an empty <li> draws a rule between groups of items.
  • The menu opens on hover as well as on click — .btn-group:hover .dropdown-menu — so it needs no script.

Rewritten and checked against 2.4-main @ 91d03d0a23 on 2026-09-10.