Tag: CSS

  • The Most Extreme CSS Reset Ever Created: 10,000 Lines of Failure

    My CSS reset exploding into a mushroom cloud
    Free fire explosion image“/ CC0 1.0

    I appreciate the intentionality of Vale’s CSS reset – everything has a reason. But what I found the most eye-opening were the links to the default stylesheets used by Chrome, Safari, and Firefox. These files are overwhelming, but the nerd in me really wanted to know what the differences were between each of them. In detail. Then I could make The One CSS Reset to Rule Them All. It would be better than normalize.css, better than the Meyer reset!

    Analyzing the Default CSS

    To do a proper analysis I needed to download the default CSS files and clean them. Safari is used by mobile, desktop, and vision and it uses directives to differentiate between them. I removed everything that wasn’t for desktop. Next, I minified each of the files to remove comments and whitespace. With clean “data” I could now analyze the files using the NPM package cssstats-cli. Here’s what I came up with.

    • Chrome is 48 KB and has 298 rules.
    • Safari is 26 KB and has 175 rules.
    • Firefox is 15 KB and has 143 rules.

    I wanted to try to see what was actually styled after the rules had been set, but it turns out this is a hard problem. I thought maybe I could write a comprehensive test page, and then programmatically walk through the document to view the computed styles for each object. Then I could compare each of the three stylesheets to see where the actual differences were.

    Finding the Differences

    Starting with the Chrome stylesheet, I worked my way through about a quarter of it, making HTML to test each ruleset. It was then that I realized testing this was going to be a nightmare. There are just so many rules, targeting so many different scenarios. Many of these scenarios would rarely be triggered. In fact, it may even be impossible. It was time for Claude to step in.

    I created a list of every selector in the default CSS files for Chrome, Safari, and Firefox. Then I asked Claude to create a single HTML file with elements that matched every selector. That gave me a massive file with about 600 elements.

    Generating the CSS Reset

    Next, I created a script to open the HTML file in each browser, using Playwright to grab the computed styles for every element. The script saved all of the computed styles to JSON files. Just a reminder that there are 520 CSS properties on every element! Finally, I created a script that compared the JSON files and for every difference, selected an appropriate default and wrote that style to a CSS file.

    The result was a 10,000-line monstrosity of a CSS reset that basically created the lowest common denominator of stylesheets. We’re talking Times New Roman on every element, font sizes set in pixels, etc. Upon visual inspection, I noticed that there were still differences. Queue the table flip. Claude and I added more code to normalize values, handling rounding of decimals, shorthand property differences, etc. The results were almost perfect, but there were still problems.

    Optimizing the Result

    After looking over the generated stylesheet, I could see that lots of similar properties were getting repeated. I thought, maybe I needed an optimization step. So, I configured it scripts to run CSSO on the generated stylesheet. That cut the size down to 5,400 lines, which was much better, but still far from what a CSS reset file should be doing. Also, it should be stated at this point that I was clearly in CSS normalization territory and not CSS reset territory. But the line between the two gets blurry.

    Nuclear CSS Reset

    It’s at this point that I came to the conclusion that if you seriously want to normalize/reset the default styles of every browser, there’s only one way to do it. Destroy all user-agent styles and then build from the ground up, styling only what you need. This is the second most extreme CSS reset ever created:

    * { all: unset }

    rip

  • Chris Coyier on CSS Module Imports

    Wow! You can now import CSS modules in Firefox. This means that it works in every browser except for Safari. Via Frontend Masters Blog

  • Details Make the Design

    I was poking around on Detail, getting some inspiration when it occurred to me that the small details really do make a big difference. I know that’s not a huge revelation, but CSS makes it incredibly easy these days.

    Chris Coyier has a post about modern CSS two-liners that have a big impact on the design of a website. Here are two more, not as fresh, n <= 2 liners.

    Page transitions

    You can put a nice fade in/out effect on the entire site in one line. Now when you navigate to any other page on the site, it will look nice and polished.

    @view-transition { navigation: auto; }

    Selection color

    Let’s not forget selection color. Of course, you can make the selection color as wild as you want, but a simple inversion of the main site colors is usually enough to make it look intentional.

    ::selection {
      color: white;
      background-color: black;
    }
  • Why I Chose Tauri for My Text Adventure Game

    When I started designing Head in the Cloud, a horror text-adventure game, I figured C would be the natural language of choice. There is a romanticism to writing a text-based game in C. But I wanted to ship the game, and I knew that C wasn’t the best choice for that (for me).

    I ultimately chose Tauri, a framework that allows you to build desktop applications using web technologies, over a traditional systems language. Here’s why.

    1. Avoiding the Language Learning Curve

    My biggest constraint was time. As a Lead Software Engineer with two decades of experience in web development, I’m most familiar with HTML, CSS, and JavaScript. Conversely, I don’t know C and my knowledge of Rust (another systems language) is novice at best.

    Choosing C would have turned this into a language learning exercise rather than a game development journey. By choosing Tauri, I eliminated the “language tax.” I can think in game logic—inventory arrays, state management, narrative branching—rather than syntax. The goal is to ship a game, not to learn a language.

    2. CSS is Great for Text, Layouts, and Graphics

    The web browser is the most sophisticated text rendering engine in existence. If I were to build in C, I would be giving that up. I also wanted keep the option to modernize the game with graphics. A text-based game benefits a lot from illustrations.

    Using Tauri allows me to use CSS. I can utilize Flexbox and Grid for responsive layouts that look good on any screen size. I can load custom web fonts to set the retro atmosphere instantly. I can use CSS animations for subtle text fades or “glitch” effects that would be nightmarish to code from scratch in C. Tauri gives me a AAA-level UI layer for free.

    3. Smaller Build Sizes than Electron

    The immediate counter-argument to using web tech for desktop apps is usually “Electron bloat.” Electron bundles a version of the Chromium browser and Node.js into every single application installer. This leads to simple chat apps weighing in at 100MB+.

    Tauri solves this by relying on the Operating System’s native webview (WKWebView on macOS, WebView2 on Windows, WebKitGTK on Linux). It does not bundle a browser.

    The result is massive binary reduction. A basic Tauri app can be less than 5MB. For a text adventure game, keeping the footprint small is essential. I get the development experience of Electron without forcing the user to download an entire web browser just to play a text game.

    4. Simpler Architecture than Electron

    While I wanted the web environment, I did not want the Electron ecosystem. Electron is powerful, but it requires you to manage the complexity of the Main vs. Renderer processes, context bridges, and inter-process communication (IPC).

    Tauri simplifies this architecture. It is built on Rust, providing a secure, lightweight backend that communicates with the frontend. I don’t have to worry about spinning up worker threads manually or managing complex menu configurations just to get a window on the screen. It provides sensible defaults that let me focus on the JavaScript layer where my game logic lives.

    5. Iteration Velocity

    Game development requires constant tweaking. You change a line of dialogue, you tweak a color, you adjust a timing delay.

    In a C environment, this is a compile-run loop. In the Tauri environment, I have access to Hot Module Replacement (HMR). I can change the CSS of the game interface or the JavaScript logic of a puzzle, and the game window updates instantly without a restart. Over the course of a 6-month development cycle, those saved seconds compound into days of saved time.

    6. Safety by Default

    Writing a game in C opens the door to memory leaks and segfaults. One bad pointer arithmetic error can crash the user’s desktop.

    Tauri relies on Rust for its backend bindings. Even though I am a Rust novice, I benefit from Rust’s memory safety guarantees. I am writing high-level JavaScript, which is sandboxed, and the heavy lifting is done by a backend that is proven to be memory-safe. It is a safety net that C simply does not offer.

    7. Cross-Platform without the Pain

    Finally, compiling C for Windows, macOS, and Linux requires managing makefiles, compiler flags, and distinct build environments. Tauri abstracts this complexity. With a few commands, I can cross-compile binaries for the major operating systems. Since the UI is just a webview, I don’t have to rewrite the rendering logic for different OS window managers. It ensures Head in the Cloud is accessible to everyone, regardless of their machine.

    Conclusion

    There is no “best” language, only the best tool for the job at hand. For a high-fidelity 3D shooter, C++ or Rust is the answer. But for a narrative-driven text adventure built by a veteran web developer? Tauri offers the perfect intersection of performance, file size, and developer velocity. It lets me respect the user’s hardware while respecting my own time.

  • More Ways CSS and HTML Can Replace JavaScript

    You No Longer Need JavaScript by Lyra Rebane

    Modern CSS and HTML can replace JavaScript for more use cases than most developers realize. The web is evolving away from JS-heavy frameworks and toward progressive enhancement.

    This article has examples of centering things, nested CSS, web components, dark mode, CSS variables, accordions, and form field validation.

  • Re-evaluate Old Web Development Habits

    NoLoJS: Reducing the JS Workload with HTML and CSS

    …as new HTML and CSS methods gain traction, we need to consider replacing some “standard” JS patterns with new methods that require no, or lo, JS.

    This article contains examples of accordions, expanding form Field elements, input with autofilter suggestions dropdown, modals and popovers, offscreen nav, smooth scrolling, and sticky content.