Skip to content

Best Practices

Building a great Basker theme means balancing aesthetics, performance, accessibility, and maintainability. This section covers best practices to help you create themes that are fast, accessible, and easy to maintain.

Performance First

Optimize images, minimize render-blocking resources, and use lazy loading to ensure fast page loads.

Accessible by Default

Build inclusive experiences that work for everyone, regardless of ability or device.

Maintainable Code

Write clean, organized Liquid templates that are easy to understand and update.

Progressive Enhancement

Start with solid HTML foundations, then layer on CSS and JavaScript enhancements.

{# Always specify dimensions and use lazy loading #}
<img
src="{{ image | image_url: width: 800, height: 600 }}"
alt="{{ image.alt | default: 'Descriptive fallback' }}"
width="800"
height="600"
loading="lazy"
>
{# Use semantic elements for better accessibility #}
<article class="event-card">
<header>
<h2>{{ event.title }}</h2>
<time datetime="{{ event.startDate }}">
{{ event.startDate | date: '%B %d, %Y' }}
</time>
</header>
<p>{{ event.description }}</p>
</article>
{# Limit iterations when possible #}
{% for event in all_events limit: 6 %}
{% render 'components/event-card' event: event %}
{% endfor %}
{# Only load what's needed #}
{% if page.theme.show_map %}
{% render 'components/map' location: venue %}
{% endif %}

Before publishing your theme, verify these essentials:

  • Images use image_url filter with appropriate dimensions
  • Off-screen images use loading="lazy"
  • CSS is minimal and scoped appropriately
  • No render-blocking JavaScript in <head>
  • Fonts are optimized (subset, preload critical fonts)
  • All images have meaningful alt text
  • Color contrast meets WCAG AA (4.5:1 for text)
  • Interactive elements are keyboard accessible
  • Form inputs have associated labels
  • Page has logical heading hierarchy (h1 → h2 → h3)
  • Templates use components for reusable patterns
  • Variables have fallback values where appropriate
  • No hardcoded content that should be configurable
  • Settings schema is well-documented
  • Consistent naming conventions throughout
  • Layout adapts to all screen sizes
  • Touch targets are at least 44×44px
  • Text is readable without zooming
  • No horizontal scrolling on mobile
{# Bad: Hard to maintain, no caching #}
<div style="background-color: {{ settings.header.background }};">
{# Better: Use CSS custom properties #}
{% stylesheet %}
:root {
--header-bg: {{ settings.header.background | default: '#ffffff' }};
}
{% endstylesheet %}
<div class="header">
{# Bad: Hard to read and maintain #}
{% if event %}
{% if event.image %}
{% if event.image.url %}
<img src="{{ event.image | image_url }}">
{% endif %}
{% endif %}
{% endif %}
{# Better: Early exit pattern #}
{% if event.image %}
<img src="{{ event.image | image_url: width: 800 }}" alt="{{ event.image.alt }}">
{% endif %}
{# Bad: Copy-pasted markup #}
<article class="event-card">...</article>
<article class="event-card">...</article>
{# Better: Use components #}
{% for event in events %}
{% render 'components/event-card' event: event %}
{% endfor %}