Skip to main content

Telephone Number Validator

Telephone Number Validator Mobile UI Preview Figma vs Visual Studio Code Telephone Number Validator Desktop UI Preview Figma vs Visual Studio Code

The Project

US phone number validator developed with Regular Expressions, responsive mobile-first design and performance-oriented architecture. An application that demonstrates the power of regex in validating complex patterns.

Source Code

<!-- DESIGN 
------
* This file contains the HTML structure of the Phone Checker application.

* The structure follows this flow:
* - Head with meta tags, CSS link, and preconnection to Google Fonts.
* - Body with main containing the primary container.
* - Container with device-frame (device bezel) that appears only on the
* desktop version.
* - Device-screen (internal screen) that contains the entire application's UI.
* - Form with input, buttons, and results area
-->

<!DOCTYPE html>
<html lang="en">
<head>
<title>Phone Checker</title>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="stylesheet" href="styles.css">
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Inter:ital,opsz,wght@0,14..32,100..900;1,14..32,100..900&display=swap" rel="stylesheet">
</head>

<body>

<!--
* freeCodeCamp instructions:
* - You should have an input element with an id of "user-input". ✔️
* - You should have a button element with an id of "check-btn". ✔️
* - You should have a button element with an id of "clear-btn". ✔️
* - You should have a div, span or p element with an id of "results-div" ✔️
-->

<!--
* I discovered that the modern approach uses classes for CSS and IDs for
* elements primarily used in JavaScript. Performance is the same, and
* counterintuitively, classes even seem faster as this article explains:
* (https://csswizardry.com/2011/09/writing-efficient-css-selectors/)
-->

<main>

<div class="container">
<div class="device-frame">
<div class="device-screen">
<p class="tribute"><a href="https://www.freecodecamp.org/" target="_blank" rel="noopener noreferrer" aria-label="Visit freeCodeCamp website (opens in new tab)">For freeCodeCamp</a></p>
<h1>Phone Checker</h1>
<form id="phone-form">
<label for="user-input">Enter a Phone Number</label>
<input type="tel" id="user-input" placeholder="1 555-555-5555" />
<div class="button-group">
<button type="submit" id="check-btn">Check</button> <!-- I must remember to add e.preventDefault() in JS -->
<button type="button" id="clear-btn">Clear</button>
</div>
<div id="results-div"></div>
</form>
</div>
</div>
</div>

</main>

<script src="script.js"></script>
</body>

</html>

The Best Project So Far

This has been the best project I've done so far. The regex was by far the most difficult part.
I didn't try other approaches: I could have handled phone number validation in alternative ways, such as a cascade of if statements. The code would have been easier to write and even easier to read, but it would have been tremendously long. Opting for regex was also a way to strengthen my understanding of it. I wrote a detailed explanation of the regex inside script.js, both to help anyone understand what each piece does and to consolidate what I learned.

The Design: HTC One M8 and Windows Phone Aesthetic

As for the design, I decided to place an HTC One M8 for Windows (the Verizon version) on a simple Windows Phone-style blue background. It turned out better than I had imagined. I tried the gold and black versions, but this silver one pairs best with the background.

Mobile-First (Really): A Conscious Choice

The mobile version is the default version. As I wrote in the styles.css comments, I chose to create a media query for desktop and no longer putting the mobile version in a media query, as I did in the past.

The reasons are twofold:

  1. Adoption: Mobile has surpassed desktop traffic for years now.
  2. Performance: By setting it as default, the device frame (the HTC) loads only when viewed from desktop. Additionally, desktop users generally have faster internet connections, so it made even more sense.

The Reflection: Mobile-First is not a Dogma

This is rarely discussed, but I believe that beyond the "mobile-first" gold standard, we should evaluate based on the device that will predominantly be used to navigate our application.
If you're creating an application primarily intended for desktop, perhaps it makes more sense to adopt the old method of dedicating a media query to mobile.
In this project, I still chose the mobile-first approach also to get used to this way of thinking, a skill I want to consolidate.
I could be wrong, but I always get red flags when I hear "that's just how it is". There are always a thousand nuances and "it depends" that often go unmentioned.

The Philosophy of Comments

As I did in the previous certification project, I paid particular attention to comments in the code. I wrote everything there: the logic, architectural choices, patterns used. Repeating it here would be redundant and, above all, difficult to understand without having the code at hand.
In this project, I decided to reduce useless comments, what antirez calls "Trivial Comments," in order to make the code cleaner. I concentrated most of the comments at the beginning of each document, creating a sort of map that guides the reading of the code without weighing it down.
I just want to say that with each passing project, my self-confidence increases and, at the same pace, my enjoyment.

What I Learned

Regular Expressions:

  • Complex patterns for US phone number validation: /^(1\s?)?(\(\d{3}\)|\d{3})[\s\-]?\d{3}[\s\-]?\d{4}$/
  • Handling optional prefixes (country code 1)
  • Alternation between formats with parentheses (\d{3}) and without \d{3}
  • Character classes [\s\-] for multiple separators
  • Anchors ^ and $ for strict validation without extra characters

Conscious Mobile-First Strategy:

  • Default CSS without media query for mobile
  • Media query @media (min-width: 560px) and (min-height: 730px) only for desktop and tablet
  • Conditional loading of device-frame (bezel) only on desktop and tablet
  • Optimization for slower mobile connections

Advanced CSS Variables:

  • Overriding CSS variables in media queries for responsive design
  • Scalable design system with semantic variables
  • Management of two complete themes (mobile/desktop) with the same set of variables

Safe DOM Manipulation:

  • .textContent for XSS sanitization before any modification
  • .innerHTML only after content validation
  • Safe pattern: sanitize → modify → insert

Dynamic Viewport:

  • min-height: 100dvh to handle dynamic mobile URL bar
  • Fallback 100vh for unsupported browsers

Performance and UX:

  • Limit maxResult = 50 to prevent DOM performance issues
  • .insertBefore() for LIFO stack of results
  • Animation @keyframes slideInFade with cubic-bezier for smooth feedback
  • Click effect with transform: perspective() for tactile feedback

Form Handling:

  • e.preventDefault() for complete control of form behavior
  • Input length validation with maxInputLength
  • Alert for immediate feedback on input errors

Code Architecture:

  • Logical separation between validation, display, and interaction
  • Structured comments with DESIGN section for architectural overview
  • Semantic naming for reusable functions

Reflection

It was essential, in creating the HTML, to test iteratively on my favorite edge case: the iPhone 12 mini and, surprisingly, also on an HTC One M8 (Android version).
I recently discovered the "ipconfig getifaddr en0" command (on macOS) in the terminal, which opened up a world to me. I added a text file to my desktop with the procedure I summarized:

  • Run ipconfig getifaddr en0 in the terminal
  • It will give you a number (n), your local IP
  • In VS Code, after clicking on Live Server, there will be the port number (p)
  • On the desired device, type in the address bar: n:p

I always close the Live Server when I'm done. Although the risk is actually low, considering that to access the port you must be on my same wifi network anyway.


Next Project: Learn Basic OOP by Building a Shopping Cart