Skip to content

Repository files navigation

Frontend Mentor — Character counter solution

This is a solution to the Character counter challenge on Frontend Mentor. Frontend Mentor challenges help you improve your coding skills by building realistic projects.

Table of contents

Overview

The challenge

Users should be able to:

  • Analyze the character, word, and sentence counts for their text in real-time
  • Exclude / include spaces in their character count
  • Set a character limit and receive a warning message if their text exceeds the limit
  • See the approximate reading time of their text
  • Analyze the letter density of their text (sorted, with "See more / See less")
  • Select their color theme (light / dark, persisted between visits)
  • View an optimized layout for mobile, tablet, and desktop
  • See hover and focus states for all interactive elements

Screenshots

Desktop — 1440px

Desktop 1440px

Mobile — 375px

Mobile 375px

Links

  • Solution URL: TBD
  • Live Site URL: TBD

My process

Built with

  • Semantic HTML5 (header, main, section, article)
  • CSS custom properties (design-token architecture, two-theme mapping)
  • Flexbox + CSS Grid
  • Mobile-first responsive design with progressive enhancement
  • Vanilla JavaScript (ES modules, no framework)
  • Vite — dev server and build tool
  • DM Sans variable font (self-hosted)

Architecture

src/
├── css/
│   ├── main.css          # entry, imports all others
│   ├── fonts.css         # DM Sans @font-face
│   ├── tokens.css        # colors, spacing, radii, typography
│   ├── theme.css         # dark (default) and light mappings
│   ├── base.css          # reset, body, focus-visible, reduced-motion
│   ├── utilities.css     # visually-hidden helper
│   ├── layout.css        # page / section layout (mobile-first)
│   ├── components.css    # brand, theme-toggle, textarea, stats, density
│   └── responsive.css    # tablet (≥640px) and desktop (≥1024px) overrides
└── js/
    ├── main.js           # DOM wiring
    ├── analyzer.js       # pure: counts, reading time, letter density
    └── theme.js          # theme toggle with localStorage persistence

What I learned

  • Centralizing every spacing, color, and typography value as a CSS custom property from the start made theme switching a one-class toggle (data-theme on :root) with no component rewrites.
  • prefers-color-scheme + localStorage gives a robust first-load theme: respect the OS preference, let the user override, remember the choice.
  • The \p{L} Unicode regex flag is a clean way to count letters across scripts without hardcoding A–Z.
  • Mobile-first beats desktop-first when the design has clear responsive tiers: overrides add behavior, never undo it.
export function computeLetterDensity(text) {
  const letters = text.toUpperCase().match(/\p{L}/gu) ?? [];
  const total = letters.length;
  const counts = new Map();
  for (const ch of letters) counts.set(ch, (counts.get(ch) ?? 0) + 1);

  return {
    total,
    entries: [...counts.entries()]
      .map(([letter, count]) => ({ letter, count, percent: (count / total) * 100 }))
      .sort((a, b) => b.count - a.count || a.letter.localeCompare(b.letter)),
  };
}

Continued development

  • Explore <output> and aria-live="polite" combinations to find the screen-reader-friendliest way to announce real-time changing counts without over-announcing each keystroke.
  • Container queries for the stat cards, so each card could adapt to its own width rather than the viewport.

AI Collaboration

  • Claude Code (Anthropic) — used for planning the phased implementation, extracting design tokens from the Figma file via the Figma MCP server, generating boilerplate for the analyzer module, and automating screenshot capture with Playwright.
  • What worked: token extraction from Figma MCP gave exact values rather than eyeballing; phased checklist kept each commit focused.
  • What didn't: initial metadata fetches hit rate limits; had to narrow requests by specific node IDs.

Author

LinkedIn GitHub Hashnode X Bluesky freeCodeCamp Frontend Mentor

About

Frontend Mentor — Character counter challenge. Vanilla HTML/CSS/JS with Vite.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages