Ghost CMS Theme CSS Editing Guide
Table of Contents
- Understanding Ghost Theme Structure
- CSS Editing Methods
- Theme Development Environment Setup
- CSS File Structure and Organization
- Code Injection Method
- Direct Theme File Editing
- Advanced CSS Techniques
- Performance Optimization
- Testing and Debugging
- Deployment Best Practices
Understanding Ghost Theme Structure
Ghost themes follow a specific directory structure that determines how CSS is loaded and applied:
theme-name/
├── assets/
│ ├── css/
│ │ ├── screen.css (main stylesheet)
│ │ ├── print.css (print styles)
│ │ └── custom.css (custom modifications)
│ ├── js/
│ └── images/
├── partials/
├── package.json
├── index.hbs
├── post.hbs
├── page.hbs
└── default.hbs
Key CSS Files
- screen.css: Primary stylesheet containing all visual styles
- print.css: Print-specific styles for better printing experience
- custom.css: Optional file for theme customizations
CSS Editing Methods
Method 1: Code Injection (Recommended for Beginners)
- Pros: No file system access required, easy to implement
- Cons: Limited to additions, cannot modify existing rules efficiently
- Best for: Small customizations, color changes, typography adjustments
Method 2: Direct Theme Editing
- Pros: Complete control, can modify any aspect
- Cons: Requires file system access, version control recommended
- Best for: Major customizations, theme development
Method 3: Child Theme Creation
- Pros: Preserves original theme, update-safe
- Cons: Requires advanced knowledge
- Best for: Extensive modifications while maintaining updateability
Theme Development Environment Setup
Local Development Setup
- Install Ghost CLI
npm install ghost-cli@latest -g
- Create Local Ghost Instance
mkdir my-ghost-site
cd my-ghost-site
ghost install local
- Access Theme Directory
cd content/themes/
- Set Up Version Control
git init
git add .
git commit -m "Initial theme backup"
Development Tools Recommended
- Code Editor: VS Code with Ghost theme extensions
- Browser DevTools: Chrome/Firefox Developer Tools
- CSS Preprocessor: Sass/SCSS for advanced development
- Build Tools: Gulp or Webpack for asset compilation
CSS File Structure and Organization
Recommended CSS Architecture
/* ==========================================================================
TABLE OF CONTENTS
========================================================================== */
/*
1. VARIABLES & MIXINS
2. BASE STYLES
3. TYPOGRAPHY
4. LAYOUT
5. COMPONENTS
6. UTILITIES
7. MEDIA QUERIES
*/
/* ==========================================================================
1. VARIABLES & MIXINS
========================================================================== */
:root {
/* Color Palette */
--primary-color: #667eea;
--secondary-color: #764ba2;
--accent-color: #f093fb;
--text-primary: #2d3748;
--text-secondary: #718096;
--bg-primary: #ffffff;
--bg-secondary: #f7fafc;
/* Typography */
--font-primary: -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;
--font-secondary: Georgia, serif;
--font-mono: 'SF Mono', Monaco, monospace;
/* Spacing */
--spacing-xs: 0.25rem;
--spacing-sm: 0.5rem;
--spacing-md: 1rem;
--spacing-lg: 2rem;
--spacing-xl: 4rem;
/* Breakpoints */
--breakpoint-sm: 576px;
--breakpoint-md: 768px;
--breakpoint-lg: 992px;
--breakpoint-xl: 1200px;
/* Shadows */
--shadow-sm: 0 1px 3px rgba(0, 0, 0, 0.12);
--shadow-md: 0 4px 6px rgba(0, 0, 0, 0.07);
--shadow-lg: 0 10px 15px rgba(0, 0, 0, 0.1);
/* Transitions */
--transition-fast: 0.15s ease;
--transition-base: 0.3s ease;
--transition-slow: 0.5s ease;
}
/* ==========================================================================
2. BASE STYLES
========================================================================== */
html {
font-size: 62.5%; /* 1rem = 10px */
scroll-behavior: smooth;
}
body {
font-family: var(--font-primary);
font-size: 1.6rem;
line-height: 1.6;
color: var(--text-primary);
background-color: var(--bg-primary);
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
}
*,
*::before,
*::after {
box-sizing: border-box;
}
/* ==========================================================================
3. TYPOGRAPHY
========================================================================== */
h1, h2, h3, h4, h5, h6 {
font-family: var(--font-primary);
font-weight: 700;
line-height: 1.2;
margin-bottom: var(--spacing-md);
color: var(--text-primary);
}
h1 { font-size: 3.2rem; }
h2 { font-size: 2.8rem; }
h3 { font-size: 2.4rem; }
h4 { font-size: 2.0rem; }
h5 { font-size: 1.8rem; }
h6 { font-size: 1.6rem; }
p {
margin-bottom: var(--spacing-md);
color: var(--text-secondary);
}
a {
color: var(--primary-color);
text-decoration: none;
transition: color var(--transition-fast);
}
a:hover {
color: var(--secondary-color);
text-decoration: underline;
}
/* ==========================================================================
4. LAYOUT
========================================================================== */
.container {
max-width: 1200px;
margin: 0 auto;
padding: 0 var(--spacing-md);
}
.site-wrapper {
min-height: 100vh;
display: flex;
flex-direction: column;
}
.site-header {
background: var(--bg-primary);
border-bottom: 1px solid #e2e8f0;
position: sticky;
top: 0;
z-index: 100;
}
.site-main {
flex: 1;
padding: var(--spacing-xl) 0;
}
.site-footer {
background: var(--bg-secondary);
padding: var(--spacing-lg) 0;
border-top: 1px solid #e2e8f0;
}
/* ==========================================================================
5. COMPONENTS
========================================================================== */
/* Navigation */
.site-nav {
display: flex;
align-items: center;
justify-content: space-between;
padding: var(--spacing-md) 0;
}
.site-nav-logo {
font-size: 2.4rem;
font-weight: 800;
color: var(--text-primary);
}
.site-nav-menu {
display: flex;
list-style: none;
margin: 0;
padding: 0;
gap: var(--spacing-lg);
}
.site-nav-menu a {
font-weight: 500;
transition: color var(--transition-fast);
}
/* Post Cards */
.post-card {
background: var(--bg-primary);
border-radius: 8px;
box-shadow: var(--shadow-md);
overflow: hidden;
transition: transform var(--transition-base), box-shadow var(--transition-base);
}
.post-card:hover {
transform: translateY(-4px);
box-shadow: var(--shadow-lg);
}
.post-card-image {
width: 100%;
height: 200px;
object-fit: cover;
}
.post-card-content {
padding: var(--spacing-lg);
}
.post-card-title {
margin-bottom: var(--spacing-sm);
font-size: 2.0rem;
}
.post-card-excerpt {
color: var(--text-secondary);
margin-bottom: var(--spacing-md);
}
.post-card-meta {
display: flex;
justify-content: space-between;
align-items: center;
font-size: 1.4rem;
color: var(--text-secondary);
}
/* Buttons */
.btn {
display: inline-block;
padding: var(--spacing-sm) var(--spacing-lg);
border: none;
border-radius: 4px;
font-size: 1.4rem;
font-weight: 600;
text-align: center;
cursor: pointer;
transition: all var(--transition-fast);
text-decoration: none;
}
.btn-primary {
background: var(--primary-color);
color: white;
}
.btn-primary:hover {
background: var(--secondary-color);
transform: translateY(-1px);
}
.btn-secondary {
background: transparent;
color: var(--primary-color);
border: 2px solid var(--primary-color);
}
.btn-secondary:hover {
background: var(--primary-color);
color: white;
}
/* ==========================================================================
6. UTILITIES
========================================================================== */
.text-center { text-align: center; }
.text-left { text-align: left; }
.text-right { text-align: right; }
.mt-0 { margin-top: 0; }
.mt-1 { margin-top: var(--spacing-xs); }
.mt-2 { margin-top: var(--spacing-sm); }
.mt-3 { margin-top: var(--spacing-md); }
.mt-4 { margin-top: var(--spacing-lg); }
.mb-0 { margin-bottom: 0; }
.mb-1 { margin-bottom: var(--spacing-xs); }
.mb-2 { margin-bottom: var(--spacing-sm); }
.mb-3 { margin-bottom: var(--spacing-md); }
.mb-4 { margin-bottom: var(--spacing-lg); }
.hidden { display: none; }
.visible { display: block; }
/* ==========================================================================
7. MEDIA QUERIES
========================================================================== */
@media (max-width: 768px) {
html { font-size: 56.25%; } /* Reduce base font size */
.container {
padding: 0 var(--spacing-sm);
}
.site-nav {
flex-direction: column;
gap: var(--spacing-md);
}
.site-nav-menu {
gap: var(--spacing-md);
}
h1 { font-size: 2.8rem; }
h2 { font-size: 2.4rem; }
h3 { font-size: 2.0rem; }
}
@media (max-width: 480px) {
.site-nav-menu {
flex-direction: column;
gap: var(--spacing-sm);
}
.post-card-content {
padding: var(--spacing-md);
}
}
Code Injection Method
Accessing Code Injection
- Navigate to Ghost Admin → Settings → Code Injection
- Three injection points available:
- Site Header: CSS and meta tags
- Site Footer: JavaScript before closing
</body>
- Post Footer: Content after each post
Site Header CSS Injection
<style>
/* Custom Theme Modifications */
/* Override primary colors */
:root {
--ghost-accent-color: #667eea;
}
/* Custom header styling */
.site-header {
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
color: white;
box-shadow: 0 2px 10px rgba(0,0,0,0.1);
}
.site-header .site-nav-logo,
.site-header .nav a {
color: white !important;
}
.site-header .nav a:hover {
color: rgba(255,255,255,0.8) !important;
}
/* Enhanced post cards */
.post-card {
border: none;
border-radius: 12px;
overflow: hidden;
transition: all 0.3s cubic-bezier(0.25, 0.8, 0.25, 1);
box-shadow: 0 2px 8px rgba(0,0,0,0.1);
}
.post-card:hover {
transform: translateY(-8px);
box-shadow: 0 12px 24px rgba(0,0,0,0.15);
}
/* Custom typography */
.post-card-title {
font-family: 'Inter', -apple-system, BlinkMacSystemFont, sans-serif;
font-weight: 700;
line-height: 1.3;
color: #1a202c;
}
.post-card-excerpt {
color: #718096;
line-height: 1.6;
}
/* Reading progress bar */
.reading-progress {
position: fixed;
top: 0;
left: 0;
width: 0%;
height: 3px;
background: linear-gradient(90deg, #667eea, #764ba2);
z-index: 9999;
transition: width 0.3s ease;
}
/* Custom button styles */
.gh-btn {
background: linear-gradient(135deg, #667eea, #764ba2);
border: none;
border-radius: 25px;
padding: 12px 24px;
color: white;
font-weight: 600;
transition: all 0.3s ease;
box-shadow: 0 4px 12px rgba(102, 126, 234, 0.3);
}
.gh-btn:hover {
transform: translateY(-2px);
box-shadow: 0 6px 16px rgba(102, 126, 234, 0.4);
}
/* Dark mode support */
@media (prefers-color-scheme: dark) {
:root {
--color-base: #ffffff;
--color-primary: #f7fafc;
--color-secondary: #e2e8f0;
--color-border: #4a5568;
--color-bg: #1a202c;
}
body {
background-color: var(--color-bg);
color: var(--color-base);
}
.post-card {
background: #2d3748;
border: 1px solid #4a5568;
}
}
/* Animation keyframes */
@keyframes fadeInUp {
from {
opacity: 0;
transform: translateY(30px);
}
to {
opacity: 1;
transform: translateY(0);
}
}
.post-card {
animation: fadeInUp 0.6s ease-out;
}
/* Responsive improvements */
@media (max-width: 768px) {
.site-header {
padding: 1rem 0;
}
.post-card {
margin-bottom: 2rem;
}
.post-card-content {
padding: 1.5rem;
}
}
</style>
Site Footer JavaScript Injection
<script>
document.addEventListener('DOMContentLoaded', function() {
// Reading progress bar
if (document.body.classList.contains('post-template')) {
const progressBar = document.createElement('div');
progressBar.className = 'reading-progress';
document.body.appendChild(progressBar);
window.addEventListener('scroll', function() {
const article = document.querySelector('.gh-content');
if (article) {
const totalHeight = article.offsetHeight;
const windowHeight = window.innerHeight;
const scrollTop = window.scrollY;
const articleTop = article.offsetTop;
const progress = Math.max(0, Math.min(100,
((scrollTop - articleTop + windowHeight) / totalHeight) * 100
));
progressBar.style.width = progress + '%';
}
});
}
// Smooth scroll for anchor links
document.querySelectorAll('a[href^="#"]').forEach(anchor => {
anchor.addEventListener('click', function (e) {
e.preventDefault();
const target = document.querySelector(this.getAttribute('href'));
if (target) {
target.scrollIntoView({
behavior: 'smooth',
block: 'start'
});
}
});
});
// Lazy load images
if ('IntersectionObserver' in window) {
const imageObserver = new IntersectionObserver((entries, observer) => {
entries.forEach(entry => {
if (entry.isIntersecting) {
const img = entry.target;
img.src = img.dataset.src;
img.classList.remove('lazy');
imageObserver.unobserve(img);
}
});
});
document.querySelectorAll('img[data-src]').forEach(img => {
imageObserver.observe(img);
});
}
});
</script>
Direct Theme File Editing
Accessing Theme Files
Via FTP/SFTP:
/var/www/ghost/content/themes/your-theme-name/assets/css/
Via Ghost Admin (if enabled): Settings → Design → Theme → Edit
Modifying screen.css
/* Add at the beginning of screen.css for better organization */
/* ==========================================================================
CUSTOM MODIFICATIONS
Add all custom styles here to make updates easier
========================================================================== */
/* Color scheme override */
:root {
--ghost-accent-color: #667eea;
--color-primary: #667eea;
--color-secondary: #764ba2;
}
/* Typography enhancements */
body {
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
line-height: 1.7;
}
h1, h2, h3, h4, h5, h6 {
font-weight: 700;
letter-spacing: -0.02em;
}
/* Header customization */
.site-header {
backdrop-filter: blur(10px);
background: rgba(255, 255, 255, 0.95);
border-bottom: 1px solid rgba(0, 0, 0, 0.1);
}
/* Post layout improvements */
.post-full-content {
max-width: 800px;
margin: 0 auto;
}
.post-full-content p {
font-size: 1.125rem;
line-height: 1.8;
margin-bottom: 1.5rem;
}
.post-full-content h2 {
margin-top: 3rem;
margin-bottom: 1rem;
font-size: 1.875rem;
}
/* Code block styling */
.post-full-content pre {
background: #1a202c;
color: #e2e8f0;
border-radius: 8px;
padding: 1.5rem;
overflow-x: auto;
font-size: 0.875rem;
line-height: 1.6;
}
.post-full-content code {
background: #f7fafc;
padding: 0.25rem 0.5rem;
border-radius: 4px;
font-size: 0.875rem;
color: #2d3748;
}
.post-full-content pre code {
background: transparent;
padding: 0;
color: inherit;
}
/* Table styling */
.post-full-content table {
width: 100%;
border-collapse: collapse;
margin: 2rem 0;
font-size: 0.9375rem;
}
.post-full-content table th,
.post-full-content table td {
padding: 0.75rem;
text-align: left;
border-bottom: 1px solid #e2e8f0;
}
.post-full-content table th {
background: #f7fafc;
font-weight: 600;
color: #2d3748;
}
/* Blockquote styling */
.post-full-content blockquote {
border-left: 4px solid var(--ghost-accent-color);
padding-left: 1.5rem;
margin: 2rem 0;
font-style: italic;
color: #4a5568;
background: #f7fafc;
padding: 1.5rem;
border-radius: 0 8px 8px 0;
}
/* Image enhancements */
.post-full-content img {
border-radius: 8px;
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);
margin: 2rem 0;
}
/* Author bio styling */
.author-card {
background: linear-gradient(135deg, #f7fafc, #edf2f7);
border-radius: 12px;
padding: 2rem;
margin: 3rem 0;
border: 1px solid #e2e8f0;
}
/* Subscribe form styling */
.subscribe-form {
background: linear-gradient(135deg, var(--ghost-accent-color), #764ba2);
color: white;
padding: 2rem;
border-radius: 12px;
text-align: center;
}
.subscribe-form input[type="email"] {
padding: 0.75rem 1rem;
border: none;
border-radius: 25px;
margin-right: 0.5rem;
font-size: 1rem;
}
.subscribe-form button {
background: rgba(255, 255, 255, 0.2);
color: white;
border: 2px solid rgba(255, 255, 255, 0.3);
padding: 0.75rem 1.5rem;
border-radius: 25px;
font-weight: 600;
cursor: pointer;
transition: all 0.3s ease;
}
.subscribe-form button:hover {
background: rgba(255, 255, 255, 0.3);
transform: translateY(-1px);
}
/* ==========================================================================
END CUSTOM MODIFICATIONS
========================================================================== */
Advanced CSS Techniques
CSS Grid Layout for Posts
.posts-grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(350px, 1fr));
gap: 2rem;
margin: 2rem 0;
}
.post-card {
display: flex;
flex-direction: column;
}
.post-card-content {
flex: 1;
display: flex;
flex-direction: column;
}
.post-card-excerpt {
flex: 1;
}
.post-card-meta {
margin-top: auto;
}
Advanced Animations
/* Scroll-triggered animations */
@keyframes slideInFromLeft {
0% {
transform: translateX(-100%);
opacity: 0;
}
100% {
transform: translateX(0);
opacity: 1;
}
}
.animate-on-scroll {
opacity: 0;
transform: translateY(20px);
transition: all 0.6s ease-out;
}
.animate-on-scroll.animated {
opacity: 1;
transform: translateY(0);
}
/* Hover effects */
.post-card {
position: relative;
overflow: hidden;
}
.post-card::before {
content: '';
position: absolute;
top: 0;
left: -100%;
width: 100%;
height: 100%;
background: linear-gradient(90deg, transparent, rgba(255,255,255,0.2), transparent);
transition: left 0.5s;
}
.post-card:hover::before {
left: 100%;
}
CSS Custom Properties for Theming
/* Light theme (default) */
:root {
--bg-primary: #ffffff;
--bg-secondary: #f7fafc;
--text-primary: #2d3748;
--text-secondary: #718096;
--border-color: #e2e8f0;
--accent-color: #667eea;
}
/* Dark theme */
[data-theme="dark"] {
--bg-primary: #1a202c;
--bg-secondary: #2d3748;
--text-primary: #f7fafc;
--text-secondary: #cbd5e0;
--border-color: #4a5568;
--accent-color: #9f7aea;
}
/* Apply variables */
body {
background-color: var(--bg-primary);
color: var(--text-primary);
transition: all 0.3s ease;
}
.post-card {
background: var(--bg-primary);
border: 1px solid var(--border-color);
color: var(--text-primary);
}
Performance Optimization
CSS Optimization Techniques
/* Use efficient selectors */
.post-card { } /* Good: class selector */
.post-card .title { } /* Good: descendant selector */
div.post-card { } /* Avoid: element + class */
* { } /* Avoid: universal selector */
/* Minimize repaints and reflows */
.post-card {
transform: translateZ(0); /* Create compositing layer */
will-change: transform; /* Hint browser for optimization */
}
/* Use transform for animations */
.post-card:hover {
transform: translateY(-4px); /* Better than changing top/margin */
}
/* Optimize images */
.post-card-image {
object-fit: cover;
width: 100%;
height: 200px;
background: #f7fafc; /* Fallback while loading */
}
Critical CSS Extraction
/* Above-the-fold critical CSS */
body, .site-header, .site-nav {
/* Include only essential styles for initial render */
}
/* Non-critical CSS - load asynchronously */
@media print {
/* Print styles */
}
.modal, .tooltip, .dropdown {
/* Interactive elements not immediately visible */
}
Testing and Debugging
Browser DevTools Usage
- Inspect Element: Right-click → Inspect
- Styles Panel: View computed styles and cascade
- Console: Check for CSS errors
- Performance Tab: Analyze rendering performance
CSS Validation
# Use CSS validators
curl -H "Content-Type: text/css" --data-binary @screen.css \
https://jigsaw.w3.org/css-validator/validator
Cross-Browser Testing
/* Browser prefixes for compatibility */
.element {
-webkit-transform: scale(1.1);
-moz-transform: scale(1.1);
-ms-transform: scale(1.1);
transform: scale(1.1);
}
/* Feature queries */
@supports (display: grid) {
.posts-container {
display: grid;
}
}
@supports not (display: grid) {
.posts-container {
display: flex;
flex-wrap: wrap;
}
}
Deployment Best Practices
Version Control
# Initialize Git repository
git init
git add assets/css/
git commit -m "Initial CSS version"
# Create backup before major changes
git branch backup-$(date +%Y%m%d)
git checkout -b feature/new-styling
Minification
/* Development version - readable */
.post-card {
background: white;
border-radius: 8px;
box-shadow: 0 2px 4px rgba(0,0,0,0.1);
transition: all 0.3s ease;
}
/* Production version - minified */
.post-card{background:#fff;border-radius:8px;box-shadow:0 2px 4px rgba(0,0,0,.1);transition:all .3s ease}
Build Process
// gulpfile.js example
const gulp = require('gulp');
const sass = require('gulp-sass');
const cleanCSS = require('gulp-clean-css');
const autoprefixer = require('gulp-autoprefixer');
gulp.task('css', function() {
return gulp.src('assets/scss/**/*.scss')
.pipe(sass())
.pipe(autoprefixer())
.pipe(cleanCSS())
.pipe(gulp.dest('assets/css/'));
});
Deployment Checklist
- [ ] Backup original theme files
- [ ] Test CSS changes in development environment
- [ ] Validate CSS syntax
- [ ] Check cross-browser compatibility
- [ ] Optimize and minify CSS
- [ ] Test responsive design on multiple devices
- [ ] Verify accessibility compliance
- [ ] Upload to production server
- [ ] Clear Ghost cache
- [ ] Test live site functionality
Troubleshooting Common Issues
CSS Not Loading
/* Check file paths in default.hbs */
<link rel="stylesheet" type="text/css" href="{{asset "css/screen.css"}}" />
/* Verify file permissions */
chmod 644 screen.css
Styles Not Applying
/* Increase specificity */
.site-main .post-card { } /* More specific */
.post-card { } /* Less specific */
/* Use !important sparingly */
.post-card {
background: white !important; /* Last resort */
}
Mobile Responsiveness Issues
/* Use proper viewport meta tag in default.hbs */
<meta name="viewport" content="width=device-width, initial-scale=1.0">
/* Test with proper breakpoints */
@media (max-width: 768px) {
.post-card {
margin-bottom: 1rem;
}
}
/* Use relative units */
.container {
width: 90%; /* Better than fixed pixels */
max-width: 1200px;
}
Performance Issues
/* Avoid expensive properties */
.element {
/* Avoid */
box-shadow: 0 0 20px rgba(0,0,0,0.5);
border-radius: 50%;
/* Better */
transform: translateZ(0); /* GPU acceleration */
will-change: transform;
}
/* Optimize animations */
@keyframes slideIn {
from { transform: translateX(-100%); }
to { transform: translateX(0); }
}
/* Instead of animating width/height */
@keyframes badSlideIn {
from { width: 0; }
to { width: 100%; }
}
Advanced Customization Examples
Custom Post Templates by Tag
/* Style posts differently based on tags */
.tag-tutorial .post-card {
border-left: 4px solid #38a169;
background: linear-gradient(135deg, #f0fff4, #c6f6d5);
}
.tag-news .post-card {
border-left: 4px solid #3182ce;
background: linear-gradient(135deg, #ebf8ff, #bee3f8);
}
.tag-review .post-card {
border-left: 4px solid #d69e2e;
background: linear-gradient(135deg, #fffaf0, #faf089);
}
Interactive Elements
/* Custom hover states */
.post-card {
cursor: pointer;
transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
}
.post-card:hover {
transform: translateY(-8px) scale(1.02);
box-shadow: 0 20px 40px rgba(0,0,0,0.15);
}
/* Loading states */
.loading {
position: relative;
overflow: hidden;
}
.loading::after {
content: '';
position: absolute;
top: 0;
left: -100%;
width: 100%;
height: 100%;
background: linear-gradient(90deg,
transparent,
rgba(255,255,255,0.4),
transparent
);
animation: loading 1.5s infinite;
}
@keyframes loading {
0% { left: -100%; }
100% { left: 100%; }
}
Advanced Layout Techniques
/* CSS Grid for complex layouts */
.post-grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
grid-auto-rows: minmax(200px, auto);
gap: 2rem;
}
/* Feature specific posts */
.post-card.featured {
grid-column: span 2;
grid-row: span 2;
}
/* Masonry-like layout with flexbox */
.masonry-container {
display: flex;
flex-direction: column;
flex-wrap: wrap;
height: 100vh;
align-content: flex-start;
}
.masonry-item {
width: 48%;
margin-bottom: 2rem;
break-inside: avoid;
}
/* Sticky elements */
.sidebar {
position: sticky;
top: 2rem;
height: fit-content;
}
SEO and Accessibility Considerations
SEO-Friendly CSS
/* Proper heading hierarchy */
h1 { font-size: 2.5rem; } /* One h1 per page */
h2 { font-size: 2rem; } /* Section headings */
h3 { font-size: 1.75rem; } /* Subsections */
/* Breadcrumb styling */
.breadcrumb {
font-size: 0.875rem;
color: #718096;
margin-bottom: 1rem;
}
.breadcrumb a {
color: inherit;
text-decoration: none;
}
.breadcrumb a:hover {
text-decoration: underline;
}
/* Schema.org structured data styling */
.hentry {
/* Article structured data */
}
.author {
/* Author information */
}
.published {
/* Publication date */
}
Accessibility Best Practices
/* Focus states for keyboard navigation */
a:focus,
button:focus,
input:focus {
outline: 2px solid #667eea;
outline-offset: 2px;
}
/* High contrast mode support */
@media (prefers-contrast: high) {
.post-card {
border: 2px solid #000;
}
a {
text-decoration: underline;
}
}
/* Reduced motion preferences */
@media (prefers-reduced-motion: reduce) {
* {
animation-duration: 0.01ms !important;
animation-iteration-count: 1 !important;
transition-duration: 0.01ms !important;
}
}
/* Screen reader only content */
.sr-only {
position: absolute;
width: 1px;
height: 1px;
padding: 0;
margin: -1px;
overflow: hidden;
clip: rect(0, 0, 0, 0);
white-space: nowrap;
border: 0;
}
/* Color contrast compliance */
:root {
--text-primary: #1a202c; /* 4.5:1 contrast ratio minimum */
--text-secondary: #4a5568; /* 3:1 for large text */
--link-color: #2b6cb0; /* Sufficient contrast */
}
Print Styles
@media print {
/* Hide navigation and non-essential elements */
.site-header,
.site-footer,
.sidebar,
.social-links,
.comments {
display: none;
}
/* Optimize typography for print */
body {
font-size: 12pt;
line-height: 1.4;
color: #000;
background: #fff;
}
/* Page breaks */
.post-card {
page-break-inside: avoid;
margin-bottom: 1cm;
}
h1, h2, h3 {
page-break-after: avoid;
}
/* Show link URLs */
a[href]:after {
content: " (" attr(href) ")";
font-size: 0.8em;
color: #666;
}
/* Remove shadows and gradients */
* {
box-shadow: none !important;
text-shadow: none !important;
background-image: none !important;
}
}
Security Considerations
CSS Security Best Practices
/* Avoid user-generated content in CSS */
/* Never do this: */
.user-style {
background: url('user-provided-url'); /* Potential XSS */
}
/* Content Security Policy headers */
/* Add to your server configuration: */
/* Content-Security-Policy: style-src 'self' 'unsafe-inline'; */
/* Sanitize dynamic values */
.dynamic-color {
/* Validate color values on server-side before output */
color: var(--validated-user-color);
}
Maintenance and Updates
Theme Update Strategy
/* Version comments */
/*
* Theme: Custom Ghost Theme
* Version: 2.1.0
* Last Updated: 2025-01-15
* Author: Your Name
*/
/* Change log */
/*
* v2.1.0 - Added dark mode support
* v2.0.0 - Major redesign with CSS Grid
* v1.5.0 - Improved mobile responsiveness
*/
/* Dependencies */
/*
* Requires: Ghost 5.0+
* Fonts: Inter (Google Fonts)
* Icons: Feather Icons
*/
Backup and Recovery
# Create automated backup script
#!/bin/bash
DATE=$(date +%Y%m%d_%H%M%S)
BACKUP_DIR="/backups/ghost-themes"
THEME_DIR="/var/www/ghost/content/themes/your-theme"
# Create backup
tar -czf "$BACKUP_DIR/theme-backup-$DATE.tar.gz" "$THEME_DIR"
# Keep only last 10 backups
ls -t "$BACKUP_DIR"/theme-backup-*.tar.gz | tail -n +11 | xargs rm -f
echo "Backup created: theme-backup-$DATE.tar.gz"
Performance Monitoring
/* Add CSS for performance monitoring */
.perf-indicator {
position: fixed;
top: 10px;
right: 10px;
background: rgba(0,0,0,0.8);
color: white;
padding: 5px 10px;
border-radius: 4px;
font-size: 12px;
z-index: 9999;
display: none;
}
/* Show in development mode */
body.development .perf-indicator {
display: block;
}
Conclusion
This comprehensive guide covers all aspects of CSS editing in Ghost CMS themes, from basic code injection to advanced theme development. Key takeaways:
- Start Simple: Use code injection for small modifications
- Plan Ahead: Create a development environment for major changes
- Follow Standards: Use semantic CSS and maintain consistency
- Test Thoroughly: Ensure cross-browser compatibility and responsiveness
- Optimize Performance: Minimize CSS and use efficient selectors
- Maintain Security: Validate user inputs and follow CSP guidelines
- Document Changes: Keep version history and change logs
- Backup Regularly: Always backup before making changes
Remember that CSS modifications can significantly impact your site's performance and user experience. Always test changes thoroughly before deploying to production, and consider the long-term maintainability of your customizations.
For additional resources and community support, visit the Ghost Developer Documentation and Ghost GitHub Repository.
This guide is maintained and updated regularly. For the latest version and additional resources, visit our documentation portal.