Joomla CSS and User.css — Custom Styling and Responsive Design
In this tutorial, you'll learn how to customize Joomla sites with CSS — using user.css for custom styles, writing responsive media queries with Bootstrap 5 breakpoints, and targeting specific pages using Joomla's built-in body classes.
What You'll Learn
- Where user.css lives and how Joomla loads it automatically
- How to add CSS files via the template editor
- The cascade order: user.css loads last, overrides everything
- Body classes in Joomla and how to use them for page-specific styling
- How to use the page class suffix from menu items
- CSS specificity rules for overriding Joomla defaults
- Bootstrap 5 responsive breakpoints in Cassiopeia
- How to write media queries for mobile-first design
- Styling custom module positions
- Dark mode customization with prefers-color-scheme
- Using Font Awesome icons in Cassiopeia
- Compiling Sass with Cassiopeia's Bootstrap source
Why It Matters
Every Joomla site needs visual customization beyond what the style editor provides. Custom CSS lets you fine-tune spacing, add animations, create unique layouts, and fix design issues without changing template files. Understanding how Joomla loads CSS, which classes are available, and how to write responsive rules gives you complete control over your site's appearance.
Real-World Use
An e-commerce site built on Joomla needs the product category page to display items in a four-column grid instead of the default three-column layout. The developer uses the body class com-content-category to target only category pages, writes a CSS rule to change the grid columns, and the rest of the site remains unchanged.
Learning Path
flowchart LR A["Child Templates"] --> B["CSS & User.css
You are here"]:::current B --> C["Extension Manager"] C --> D["Components"] classDef current fill:#38bdf8,color:#0f172a,stroke-width:2px
Where User.css Lives
The user.css file is located at:
templates/cassiopeia/css/user.css
If the file exists, Cassiopeia loads it automatically on every page. You do not need to edit any template file to include it.
If the file does not exist, you can create it:
# Create user.css for Cassiopeia
touch templates/cassiopeia/css/user.css
You can create the file via FTP, the command line, or through Joomla's built-in template editor.
Creating user.css via the Template Editor
- Go to Extensions > Templates > Templates
- Click Cassiopeia
- Open the Stylesheets folder in the file tree
- Click New File
- Name it user.css
- Click Create
- Edit the file and click Save
# Steps to create user.css via admin
# Extensions > Templates > Templates > Cassiopeia
# Click "New File" button
# Enter: user.css
# Select: css/ folder
# Create > Edit > Save
How the Cascade Works
CSS stands for Cascading Style Sheets. The cascade determines which rule takes priority when multiple rules apply to the same element. In Cassiopeia, the load order is:
- Bootstrap 5 CSS (from media/vendor/bootstrap/)
- Cassiopeia's template.css
- Any extension CSS loaded by plugins or components
- user.css (loads last, highest priority)
Because user.css loads last, your custom rules override everything above, provided you use equal or higher specificity.
<!-- The actual load order in the page head -->
<link href="/media/vendor/bootstrap/css/bootstrap.min.css" rel="stylesheet">
<link href="/templates/cassiopeia/css/template.css" rel="stylesheet">
<link href="/templates/cassiopeia/css/user.css" rel="stylesheet">
Body Classes in Joomla
Joomla adds several CSS classes to the <body> element on every page. These classes let you target specific pages, components, or menu items.
<!-- Example body tag on an article page -->
<body class="com-content-article itemid-123">
Common body classes:
| Class | When It Appears |
|---|---|
com-content-article |
Viewing a single article |
com-content-category |
Viewing a category list |
com-content-category-blog |
Viewing a category blog |
com-content-featured |
Viewing featured articles |
com-contact-contact |
Viewing a single contact |
com-banners-banner |
Viewing a banner |
com-users-login |
Viewing the login page |
itemid-NUMBER |
The menu item ID for the current page |
option-com_content |
Always present on com_content pages |
view-article |
View name |
layout-default |
Layout name |
Using Body Classes for Page-Specific Styling
/* Target only the blog category page */
.com-content-category-blog .blog-items {
display: grid;
grid-template-columns: repeat(3, 1fr);
gap: 20px;
}
/* Target only the single article view */
.com-content-article .page-header h2 {
font-size: 2.5rem;
color: var(--cassiopeia-color-primary);
}
/* Target a specific page by menu item ID */
.itemid-456 .article-info {
background-color: #f0f8ff;
padding: 15px;
border-radius: 8px;
}
Page Class Suffix
You can add a custom class to the body tag through the menu item settings:
- Go to Menus > [Your Menu] > [Your Menu Item]
- Find the Options tab (or Advanced tab)
- Look for "Page Class" or "Page Class Suffix"
- Enter a class name like "landing-page"
- Save
<!-- Resulting body tag -->
<body class="com-content-article itemid-123 landing-page">
Now you can target that specific page:
/* Target only the landing page */
.landing-page .hero {
background-color: #1a365d;
color: #ffffff;
padding: 60px 0;
}
.landing-page .hero h1 {
font-size: 3rem;
font-weight: 800;
}
.landing-page .hero p {
font-size: 1.25rem;
opacity: 0.9;
}
CSS Specificity
When overriding Joomla styles, you need to match or beat the specificity of the original rule. Cassiopeia uses a combination of class selectors and sometimes IDs.
/* Original Cassiopeia rule — high specificity */
.com-content-article .com-content-article__body p {
line-height: 1.8;
margin-bottom: 1rem;
}
/* Your override — needs equal or higher specificity */
.com-content-article .com-content-article__body p {
line-height: 2;
margin-bottom: 1.5rem;
}
/* If the rule uses !important in template.css, use !important in user.css */
/* Only as a last resort */
CSS specificity hierarchy (highest to lowest):
- Inline styles (
style="...") - IDs (
#my-id) - Classes, attributes, pseudo-classes (
.my-class,[type="text"],:hover) - Elements, pseudo-elements (
div,p,::before)
When you cannot override a style, inspect the element in your browser's developer tools to see which rule is winning and why.
Responsive Breakpoints
Cassiopeia uses Bootstrap 5 breakpoints. You use these in your media queries.
| Breakpoint | Class Infix | Min Width | Description |
|---|---|---|---|
| Extra small | (none) | < 576px | Mobile phones |
| Small | sm | >= 576px | Large phones |
| Medium | md | >= 768px | Tablets |
| Large | lg | >= 992px | Desktops |
| Extra large | xl | >= 1200px | Large desktops |
| Extra extra large | xxl | >= 1400px | Wide screens |
Writing Mobile-First CSS
Bootstrap 5 follows a mobile-first approach. Write base styles for small screens, then add media queries for larger screens:
/* Base style — applies to all screens, including mobile */
.blog-items {
display: grid;
grid-template-columns: 1fr;
gap: 15px;
}
/* Tablet and up — 2 columns */
@media (min-width: 768px) {
.blog-items {
grid-template-columns: repeat(2, 1fr);
}
}
/* Desktop and up — 3 columns */
@media (min-width: 992px) {
.blog-items {
grid-template-columns: repeat(3, 1fr);
}
}
/* Large desktop — 4 columns */
@media (min-width: 1200px) {
.blog-items {
grid-template-columns: repeat(4, 1fr);
}
}
Max-Width Queries for Overriding Specific Ranges
Sometimes you need styles that only apply below a certain width:
/* Mobile only — hide sidebar on small screens */
@media (max-width: 767.98px) {
.sidebar-right {
display: none;
}
}
/* Tablet only — between 768px and 991px */
@media (min-width: 768px) and (max-width: 991.98px) {
.sidebar-right {
width: 50%;
}
}
Styling Custom Module Positions
Each module position in Cassiopeia gets a CSS class based on the position name. You can target positions to apply consistent styling:
/* Target all modules in the sidebar-right position */
.sidebar-right .moduletable {
margin-bottom: 30px;
padding: 20px;
background-color: #f8f9fa;
border-radius: 8px;
border: 1px solid #e9ecef;
}
/* Target a specific module by its module class suffix */
.my-custom-class .moduletable h3 {
color: var(--cassiopeia-color-primary);
border-bottom: 2px solid var(--cassiopeia-color-primary);
padding-bottom: 10px;
}
Dark Mode Customization
Cassiopeia supports dark mode through the prefers-color-scheme media query. You can extend or override the default dark mode styles:
/* Override Cassiopeia's dark mode colors */
@media (prefers-color-scheme: dark) {
:root {
--cassiopeia-color-primary: #60a5fa;
--cassiopeia-color-text: #e2e8f0;
--cassiopeia-color-body-bg: #0f172a;
--cassiopeia-color-header-bg: #1e293b;
--cassiopeia-color-sidebar-bg: #1e293b;
--cassiopeia-color-footer-bg: #020617;
}
/* Custom dark mode additions */
.moduletable {
background-color: #1e293b;
border-color: #334155;
}
img {
opacity: 0.9;
}
}
Font Awesome Icons
Cassiopeia includes Font Awesome 5 (free version). You can use icons in your CSS:
/* Add an icon before external links */
a[target="_blank"]::after {
content: "\f35d";
font-family: "Font Awesome 5 Free";
font-weight: 900;
margin-left: 5px;
font-size: 0.8em;
}
/* Style module titles with icons */
.sidebar-right .moduletable h3::before {
content: "\f15c";
font-family: "Font Awesome 5 Free";
font-weight: 900;
margin-right: 8px;
color: var(--cassiopeia-color-primary);
}
Adding Custom CSS Files
If user.css becomes very large, you can split it into multiple files and load them separately:
- Create your file at templates/cassiopeia/css/custom-styles.css
- Load it in index.php or use Joomla's API
To load via index.php override:
// In templates/cassiopeia/index.php (use child template or override)
$template = $app->getTemplate();
$wa = $app->getDocument()->getWebAssetManager();
$wa->registerAndUseStyle('custom', Uri::root() . 'templates/' . $template . '/css/custom-styles.css');
Compiling Sass
Cassiopeia's CSS is compiled from Sass source files. The source files are in:
# Cassiopeia Sass source (if included with your installation)
templates/cassiopeia/sass/
├── template.scss
├── _variables.scss
└── _cassiopeia.scss
If you know Sass, you can override variables in custom.scss:
// templates/cassiopeia/sass/custom.scss
// Override Bootstrap variables
$primary: #2563eb;
$font-family-sans-serif: "Inter", system-ui, -apple-system, sans-serif;
$border-radius: 0.5rem;
// Import Cassiopeia
@import "template";
Then compile it:
# Compile Sass to CSS (requires Node.js and node-sass or Dart Sass)
sass templates/cassiopeia/sass/custom.scss templates/cassiopeia/css/custom.css
Debugging CSS
Use your browser's developer tools to inspect Joomla's CSS:
- Right-click any element on the page
- Click Inspect (or Inspect Element)
- In the Styles panel, you see all CSS rules affecting the element
- Crossed-out rules are overridden by higher-specificity rules
- You can toggle rules on and off to test changes
The browser's developer tools also show you the body classes, which makes targeting specific pages much easier.
Common Mistakes
Using user.css without checking specificity: You write
p { color: red; }but the paragraph text stays blue. Cassiopeia's rule.com-content-article p { color: blue; }has higher specificity. Use the same selector chain in your user.css.Not using body classes for page-specific styles: You add a global style that affects every page, when you only wanted to target the home page. Use the body class to scope your styles to specific pages.
Forgetting to account for responsive breakpoints: Your custom layout looks perfect on desktop but breaks on mobile. Always write mobile-first CSS and test at all breakpoints.
Overusing !important: You add
!importantto override a stubborn rule. Now every future CSS change also needs!important. This creates a maintenance nightmare. Use specificity instead.Editing template.css instead of user.css: Cassiopeia's template.css is overwritten during updates. Put all custom styles in user.css, which persists across updates.
Practice Questions
What is the load order of stylesheets in Cassiopeia? Answer: Bootstrap 5 loads first, then template.css, then any extension CSS, then user.css last. Because user.css loads last, it overrides all previous styles when specificity is equal.
How can you apply custom CSS to only one page on your Joomla site? Answer: Two ways: use the body class
itemid-NUMBERwhere NUMBER is the menu item ID, or add a Page Class Suffix in the menu item's Options tab and use that class in your CSS.What are the Bootstrap 5 breakpoints and their minimum widths? Answer: sm >= 576px, md >= 768px, lg >= 992px, xl >= 1200px, xxl >= 1400px. The default (xs) is < 576px.
Challenge: Create a Responsive Design system in user.css for a multi-section Joomla site. The home page should have a full-width hero section with a dark background. Category blog pages should display articles in a 2-column grid on tablet and 3 columns on desktop. Article pages should have a wider content area and styled blockquotes. The submit button on the contact page should use the accent color. Use only body classes for targeting — no IDs, no inline styles.
FAQ
Mini Project
Your task: Redesign a Joomla site's visual appearance using only user.css.
- Create or open user.css at templates/cassiopeia/css/user.css.
- Change the site's link color to a deep blue (#1e40af).
- Add a subtle background pattern to the page body.
- Style the footer with a dark background and light text.
- Make the blog category page show articles in a responsive grid (1 column mobile, 2 tablet, 3 desktop).
- Add a hover animation on article images (slight scale transform).
- Style the login page with a centered card layout.
- Add a custom bullet style for unordered lists.
- Change the blockquote styling with a left border accent.
- Add a smooth scroll behavior to the page.
- Test all changes at mobile, tablet, and desktop breakpoints.
- Verify that the page class suffix targeting works by adding a custom class to one page.
This project gives you complete hands-on experience with Joomla CSS customization — a skill you use on every site you build.
What's Next
Now that you can style your Joomla site with CSS, you are ready to learn about extensions:
Continue to Lesson 20: Extension Manager — Learn how to install, update, and manage Joomla extensions.
Related lessons:
- Joomla Template Basics — Understand template structure
- Joomla Template Overrides — Combine CSS with layout overrides
Built by the developers of DodaTech
Doda Browser, DodaZIP & Durga Antivirus Pro