• Stars
    star
    533
  • Rank 83,238 (Top 2 %)
  • Language
    HTML
  • License
    MIT License
  • Created about 1 year ago
  • Updated 3 months ago

Reviews

There are no reviews yet. Be the first to send feedback to the community and the maintainers!

Repository Details

๐ŸŒ˜ Scope your inline style tags in pure vanilla CSS! Only 16 lines. No build. No dependencies.

๐ŸŒ˜ CSS Scope Inline

cover (Art by shahabalizadeh)

Why does this exist?

  • You want an easy inline vanilla CSS experience without Tailwind CSS.
  • Hate creating unique class names over.. and over.. to use once.
  • You want to co-locate your styles for โšก๏ธ Locality of Behavior (LoB)
  • You wish this would work in <style> tags.
  • Want all CSS features: Nesting, animations. Get scoped @keyframes!
  • You wish @media queries were shorter for responsive design.
  • Only 16 lines. No build step. No dependencies.
  • Pairs well with htmx and Surreal
  • Want fewer layers, less complexity. Are aware of the cargo cult. โœˆ๏ธ

โœจ Want to also scope your <script> tags? See our companion project Surreal

๐Ÿ‘๏ธ How does it look?

<div>
    <style>
        me { background: red; } /* โœจ this & self also work! */
        me button { background: blue; } /* style child elements inline! */
    </style>
    <button>I'm blue</button>
</div>

See the Live Example! Then view source.

๐ŸŒ˜ How does it work?

This uses MutationObserver to monitor the DOM, and the moment a <style> tag is seen, it scopes the styles to whatever the parent element is. No flashing or popping.

This method also leaves your existing styles untouched, allowing you to mix and match at your leisure.

๐ŸŽ Install

โœ‚๏ธ copy + ๐Ÿ“‹ paste the snippet into <script> in your <head>

Or, ๐Ÿ“ฅ download into your project, and add <script src="script.js"></script> in your <head>

Or, ๐ŸŒ CDN: <script src="https://cdn.jsdelivr.net/gh/gnat/css-scope-inline@main/script.js"></script>

๐Ÿค” Why consider this over Tailwind CSS?

Use whatever you'd like, but there's a few advantages with this approach over Tailwind, Twind, UnoCSS:

  • No more repeating styles on child elements (..no @apply, no [&>thing] per style). It's just CSS!
  • No endless visual noise on every <div>. Use a local <style> per group.
  • No high risk of eventually requiring a build step.
  • No chance of deprecations. 16 lines is infinitely maintainable.
  • Get the ultra-fast "inspect, play with styles, paste" workflow back.
  • No suffering from FOUC (a flash of unstyled content).
  • Zero friction movement of styles between inline and .css files. Just replace me
  • No special tooling or plugins to install. Universal vanilla CSS.

โšก Workflow Tips

  • Flat, 1 selector per line can be very short like Tailwind. See the examples.
  • Use just plain CSS variables in your design system.
  • Use the short @media queries for responsive design.
    • Mobile First (flow: above breakpoint): ๐ŸŸข None sm md lg xl xx ๐Ÿ
    • Desktop First (flow: below breakpoint): ๐Ÿ xs- sm- md- lg- xl- ๐ŸŸข None
    • ๐ŸŸข = No breakpoint. Default. See the Live Example!
    • Based on Tailwind breakpoints. We use xx not 2xl to not break CSS highlighters.
    • Unlike Tailwind, you can nest your @media styles!
  • Positional selectors may be easier using div[n1] for <div n1> instead of div:nth-child(1)
  • Try tools like- Auto complete styles: VSCode or Sublime

๐Ÿ‘๏ธ CSS Scope Inline vs Tailwind CSS Showdowns

Basics

Tailwind verbosity goes up with more child elements.

<!-- CSS Scope Inline -->
<div>
    <style>
        me { background: red; }
        me div { background: green; }
        me div[n1] { background: yellow; }
        me div[n2] { background: blue; }
    </style>
    red
    <div>green</div>
    <div>green</div>
    <div>green</div>
    <div n1>yellow</div>
    <div n2>blue</div>
    <div>green</div>
    <div>green</div>
</div>

<!-- Tailwind -->
<div class="bg-[red]">
    red
    <div class="bg-[green]">green</div>
    <div class="bg-[green]">green</div>
    <div class="bg-[green]">green</div>
    <div class="bg-[yellow]">yellow</div>
    <div class="bg-[blue]">blue</div>
    <div class="bg-[green]">green</div>
    <div class="bg-[green]">green</div>
</div>

CSS variables and child styling

<!doctype html>
<html>
    <head>
        <style>
            :root {
                --color-1: hsl(0 0% 88%);
                --color-1-active: hsl(214 20% 70%);
            }
        </style>
        <script src="https://cdn.tailwindcss.com"></script>
        <script src="https://cdn.jsdelivr.net/gh/gnat/css-scope-inline@main/script.js"></script>
    </head>
    <body>
        <!-- CSS Scope Inline -->
        <div>
            <style>
               me { margin:8px 6px; }
               me div a { display:block; padding:8px 12px; margin:10px 0; background:var(--color-1); border-radius:10px; text-align:center; }
               me div a:hover { background:var(--color-1-active); color:white; }
            </style>
            <div><a href="#">Home</a></div>
            <div><a href="#">Team</a></div>
            <div><a href="#">Profile</a></div>
            <div><a href="#">Settings</a></div>
            <div><a href="#">Log Out</a></div>
        </div>

        <!-- Tailwind Example 1 -->
        <div class="mx-2 my-4">
            <div><a href="#" class="block py-2 px-3 my-2 bg-[--color-1] rounded-lg text-center hover:bg-[--color-1-active] hover:text-white">Home</a></div>
            <div><a href="#" class="block py-2 px-3 my-2 bg-[--color-1] rounded-lg text-center hover:bg-[--color-1-active] hover:text-white">Team</a></div>
            <div><a href="#" class="block py-2 px-3 my-2 bg-[--color-1] rounded-lg text-center hover:bg-[--color-1-active] hover:text-white">Profile</a></div>
            <div><a href="#" class="block py-2 px-3 my-2 bg-[--color-1] rounded-lg text-center hover:bg-[--color-1-active] hover:text-white">Settings</a></div>
            <div><a href="#" class="block py-2 px-3 my-2 bg-[--color-1] rounded-lg text-center hover:bg-[--color-1-active] hover:text-white">Log Out</a></div>
        </div>

        <!-- Tailwind Example 2 -->
        <div class="mx-2 my-4
            [&_div_a]:block [&_div_a]:py-2 [&_div_a]:px-3 [&_div_a]:my-2 [&_div_a]:bg-[--color-1] [&_div_a]:rounded-lg [&_div_a]:text-center
            [&_div_a:hover]:bg-[--color-1-active] [&_div_a:hover]:text-white">
            <div><a href="#">Home</a></div>
            <div><a href="#">Team</a></div>
            <div><a href="#">Profile</a></div>
            <div><a href="#">Settings</a></div>
            <div><a href="#">Log Out</a></div>
        </div>
    </body>
</html>

๐Ÿ”Ž Technical FAQ

  • Why do you use querySelectorAll() and not just process the MutationObserver results directly?
    • Processing MutationObserver results will work well until you begin recieving subtrees (ex: DOM swap, htmx, ajax, jquery) which requires you to walk all subtree child elements to not miss a <style>. This can involve re-scanning thousands of repeated elements, and querySelectorAll() ends up the simplicty and performance winner.

More Repositories

1

surreal

๐Ÿ—ฟ Mini jQuery alternative. Dependency-free animations. Locality of Behavior. Use one element or arrays transparently. Pairs with htmx. Vanilla querySelector() but better!
JavaScript
1,209
star
2

simple-php-form

๐Ÿ“ Easily create and validate HTML forms in PHP 8.
PHP
27
star
3

nc-cms

๐Ÿ’ก Embeddable, lightweight, simple PHP CMS. Content Management System.
PHP
26
star
4

csrf-starlette-fastapi

Dead simple CSRF security middleware for Starlette โญ and FastAPI โšก
Python
26
star
5

text-to-speech-ubuntu

๐Ÿ™Š Setup "selectable" text to speech / TTS on Ubuntu Linux 24.04 22.04 22.10 23.04 23.10 . Ideal for speed reading, programming, editing and writing.
22
star
6

doit.sh

๐Ÿดโ€โ˜ ๏ธ Replaces your build system with 1 shell script.
Shell
17
star
7

css-reset-tiny

โ™ป๏ธ Under 12 line zero bullshit modern vanilla CSS reset.
CSS
16
star
8

awesome-surreal

๐Ÿ—ฟ A curated list of awesome Surreal examples, plugins, resources and other shiny things.
15
star
9

sublime-outline-notes-publisher

โœ’๏ธ Publish HTML from markdown or tab indented notes. Static site generator in Sublime Text! Alternative to Obsidian.
Python
13
star
10

hyperscript-sublime

Hyperscript syntax highlighting for Sublime Text. (_hyperscript, HTMX)
10
star
11

sublime-invader-zim

๐Ÿ›ธ Dark Color Theme for Sublime Text 4
9
star
12

send-to-discord.sh

๐Ÿ’ฌ Message your Discord server. No setup. Zero dependencies. Just works on any of: bash, sh, curl, github actions, workflows, gitea... Uses webhooks api.
Shell
7
star
13

tetris-machine

๐ŸŽฎ 3D Tetris in pure C using OpenGL & SDL.
C
7
star
14

super-score

๐ŸŽฏ Game leaderboards, currency log, and player data storage. REST API server in PHP 7.
PHP
6
star
15

expose-ubuntu-mate

๐Ÿ‘๏ธ Setup "overview screen" for Ubuntu MATE. Similar to: OS X Expose, KDE Overview, GNOME Activities.
4
star
16

vscode-python-highlight-html-sql

Highlight HTML, SQL in Python Strings for VSCode, Codium. Embed HTML, PHP, Python Server Pages style.
3
star
17

stylus-inline

Zero build step version of Stylus CSS that runs in your browser. With inlined scopes! Written in vanilla JS. Also single file python version!
HTML
2
star
18

internet-ip-gui-linux

:godmode: Find your Internet IP & Local IP address in copy-paste format. (Global public IP for game servers).
Python
2
star
19

sublime-python-html-sql

HTML + SQL highlighter extension for strings in Python for Sublime Text!
2
star
20

api.php

Easily build an Internet API in a single file using PHP
PHP
2
star
21

super-chatendo

๐Ÿ’ฌ Real time Twitch-Slack chat in Node and Web Sockets using Socket.io.
JavaScript
1
star
22

python-replace-case-insensitive

๐Ÿ” Case insensitive string replace() alternative for Python 3. Does NOT use regex (regular expressions) in order to prevent ReDoS attacks.
Python
1
star
23

vscode-ghostbusters

๐Ÿ‘ป Dark Color Theme for VSCode / VSCodium
1
star
24

html-dialog-animated-demo

Minimalist animated HTML <dialog> element / tag demo.
HTML
1
star
25

salesforce-to-zendesk

๐Ÿšš Salesforce to Zendesk customer integration microservice.
PHP
1
star
26

rootless-docker-file-ownership

๐Ÿ‘ค Reclaim file ownership back to user who starts a rootless container (1000), from the container operating User (100998, 100000 ...)
Shell
1
star