Stefan Judis Web Development
I love building things for the web. And I love writing sharing things about the web.
Web developmentJavaScript / TypeScriptFrontend / CSS / browsers
- Posts
- 321 from 29 Jan 2020 to 18 Oct 2026
- Posting
- weekly (44 in the last year)
- Kind
- personal blog
- Feed
- https://www.stefanjudis.com/rss.xml
2026 35
- Blake Watson on the state of the industry (#note)
- Web Weekly #201 (#blogPost)
- Web Weekly #200 (#blogPost)
- Sally Hall on being proud of doing the work (#blogPost)
- Web Weekly #199 (#blogPost)
- Web Weekly #198 (#blogPost)
- Web Weekly #197 (#blogPost)
- Michelle Barker on Stage Fright (#note)
- Web Weekly #196 (#blogPost)
- Escape from Average (#note)
- Web Weekly #195 (#blogPost)
- Web Weekly #194 (#blogPost)
- Web Weekly #193 (#blogPost)
- Web Weekly #192 (#blogPost)
- Web Weekly #191 (#blogPost)
- Web Weekly #190 (#blogPost)
- Web Weekly #189 (#blogPost)
- Web Weekly #188 (#blogPost)
- Intl can localize units, too! (#tilPost)
- The scope of type guards and assertion functions (#tilPost)
- Web Weekly #187 (#blogPost)
- Web Weekly #186 (#blogPost)
- Web Weekly #185 (#blogPost)
- New lines are removed from WHATWG URLs (#tilPost)
- Nobody owes you anything (#blogPost)
- How to scale elements and their layout with CSS "zoom"
- Notes on relying on the ARIA Authoring Practices Guide
- How to style the found search / "find in page" substrings
- Clean up your Mac with open source
- ARIA roles can remove their children’s semantics
- The Trust Equation
- Firefox DevTools hides unreferenced CSS variables
- If you don't care, I don't care...
- Automatically load .env files in Node.js scripts
- A ready-to-use diff component
2025 49
- Feature detection of View Transition Types
- Simon Willison on delivering AI generated code
- light-dark() isn't always the same as prefers-color-scheme
- Three conditional border-radius CSS snippets
- Syntax-highlighting for JS template strings in VS Code
- A Raycast confetti shell command
- How to "officially" deprecate methods with Node.js utilities
- pathLength makes makes SVG path animations easier to manage
- Chrome supports split views (behind a flag)
- Stop citing AI
- Quoting Pablo Enoc
- Turn off macOS Liquid Glass via the CLI
- field-sizing isn't only about growing textareas
- Header & footer elements change their roles when they're inside of sectioning content
- I disabled my YouTube "Home" feed and I might like it
- Node.js includes a native glob utility
- Keyframe animations have a special role in the CSS cascade
- When AI will browse the web for me
- How I record, edit and publish YouTube videos
- Tag, you're it
- IntelliSense in the VS Code terminal
- Node.js supports import maps
- Talking about the Polypane browser with Kilian Valkhof
- Quoting Jeffrey Zeldman
- Open new tabs next to the current one in Firefox
- The Internet Archive opt out itch
- Stringly Typed
- Forbidden headers can't be set in "fetch" requests
- WCAG success criteria that can't be autmatically tested
- The macOS inline dictionary has a shortcut
- Query "newly" available baseline features in Node.js
- Thoughts on close requests for dialogs
- parseInt parses anything starting with a number
- TypeScript "strictFunctionTypes" is ignored for method syntax
- Rerun commands with the built-in "r" command
- How to iterate over TypeScript union types
- How to apply a global Git commit template
- A well-known avatar URL would be dang cool.
- The difference between @ts-ignore and @ts-expect-error
- How to load images in a spreadsheet
- Playwright has an experimental CLI watch mode
- Load the default OS font with CSS
- A "section" without an accessible name is nothing but a "div"
- Open a new project in the same VS Code window
- Template Literal Types for validating files names
- Static initialization blocks in JavaScript classes
- Use "translate" to turn off element translations
- Default Apps 2024
- Duplicated CSS @keyframes properties are valid
2024 44
- To blog something to show
- Hide object properties with JavaScript symbols
- How to open a local file from the URL bar in VS Code
- An API to access browser support and baseline data
- Earlier function parameters are available to default parameters
- Navigate your shell history with CTRL keys
- A web component to show browser support and baseline status
- How to search for strings in Git commit additions or deletions
- Notes on the vanishing .io toplevel domain
- Set the default time zone in Node.js
- Processes and rules make code review less intimidating
- On being a "JavaScript framework developer"...
- The order of accessible name computation steps
- A shortcut to edit long shell commands in your $EDITOR
- Space shuttle style coding
- Forms without an accessible name are not exposed as ARIA landmarks
- Construct query strings from FormData
- Web content, the social contract and copyrights
- Safari 18 — what web features are usable across browsers?
- Support your local content dealers
- Investigating INP issues
- Target=_blank implies rel=noopener
- VS Code's new minimap section headers
- Disable Angular's scroll position restoration for specific routes
- Reveal an image with smart padding
- Index images, videos and news with specialized sitemaps
- Why do I fail at achieving personal goals?
- Bun's trusted dependencies
- Unit testing AI apps
- Reasons for opening links in a new tab
- Timestamped Git yolo commits
- disabled vs aria-disabled on form elements
- Auto-margin works with absolute positioned elements
- A list of design inspiration lists
- The death of custom media queries
- Readonly files in VSCode
- Forever projects
- htmz — a 176 bytes htmx alternative
- How to type fixed string value combinations with template literal types
- Fading out text with CSS
- How to turn off password managers for fields
- Accessible notifications
- How to exclude elements from being shown in Google Search results
- How to do math in shell environments (bash, zsh, ...)
2023 43
- Local link targets must be focusable to prevent accessibility issues
- CSS only "scroll-to-top"
- A web component to make your text sparkle
- oklch() retains perceived lightness for different hue angles
- Too small touch targets
- JS surprise: Array.every() always returns true for empty arrays
- How to style element descendants with Tailwind CSS
- How to escape CSS selectors in JavaScript
- How to validate URLs in JavaScript (2023 edition)
- Conversation closure
- Fancy SVG filters
- How to remove all event listeners from a DOM element
- How to use headless Chrome in serverless functions with a 50MB limit
- How to show TypeScript type annotations in code snippets
- Copy an array and replace one element at a specific index with modern JavaScript
- How to prerender Tweets without using the official Twitter APIs
- Why do visually hidden CSS classes define a size of 1x1?
- Self-closing tags are mostly meaningless in HTML
- The "DomInteractive" event and a browser metrics deep dive
- How to use EventTarget as a web-native event emitter
- A ::selection web compatibility issue
- Safari allows to configure password autofilling
- Resumability, compilers and event delegation
- The lie of YouTube's privacy-enhanced embed mode
- Slice — an app to remove variable font axes
- Glyphhanger — a tool to subset and optimize fonts
- How to show more than ten results per page on Google Search
- The relative font weight axis — how variable fonts ease font weight transitions
- New on the web: How to detect disabled JavaScript in CSS
- Make a PDF look like it was manually scanned
- Size container queries can detect landscape / portrait orientation
- VS Code extensions to ease navigating code
- Cool URIs don't change
- YAML provides 9 ways to handle strings
- The problem of breaking changes and version numbers
- How to safely remove untracked files from Git repos
- A userland React hook for managing global state
- Git-based dotfile management without symlinks
- How to narrow and secure types with const assertions
- macOS offers a tool to remove backgrounds from images
- How to fail function calls with undefined arguments with a one-liner (sorta)
- Why doesn't JSON support comments?
- A CSS-based background grid generator
2022 70
- How to disable Google sign-in prompts on other sites
- How to animate an element's height with CSS grid
- Viewport units can consider the writing mode
- How to use Raycast snippet auto expansion
- How to split JavaScript strings into sentences, words or graphemes with "Intl.Segmenter"
- Elements can be visible even though their parent has set "visibility: hidden"
- Should responsive images work with container queries?
- Top-level promise handling in Node.js ES modules
- The missing bridge in web development – JSON forms
- CSS clip-path can go outside of an element
- How to flip characters and words in your terminal
- A native shell alternative to the trash-cli
- A JavaScript-free custom element implementation
- A centered CSS grid with full-width components
- How to find all render-blocking resources with JavaScript
- Web Almanac Highlights 2022
- An app to open your current finder directory in VS Code
- Why custom properties don't work with the url() CSS function
- Overwriting an element's accessible name can break speech recognition
- How to detect if a font is supported
- All browsers adopted :focus-visible in their UA stylesheets
- Disabled JavaScript turns off native lazy loading
- How to force push git branches without the --force flag
- How to exclude commits from git blame
- New in VS Code – Sticky Scroll
- How to create a module-based Node.js executable
- Import maps will improve cache busting
- The CSS quantity query with :nth-last-child()
- em and strong are not announced by screen readers
- How to select the previous sibling of an element
- Suffix aliases (-s) in Zsh
- How to create an API wrapper using a JavaScript proxy
- "fetch" supports a "keepAlive" option to make it outlive page navigations
- Firefox DevTools provide a multiline JavaScript console
- How to specify the start of an ordered HTML list
- Should browsers offer site-specific user preference controls? (yes!)
- How to navigate to the git root directory
- How to enforce pinch-to-zoom on Firefox/Chrome on Android
- Table cells support a "headers" HTML attribute
- A clipboard magic trick - how to use different MIME types with the Clipboard API
- Keyboard button clicks with Space and Enter behave differently
- Global fetch landed in Node 18
- How to measure network quality (download/upload) on macOS
- Google Docs supports Markdown syntax
- Twitter started to mess with embedded content on your site
- The "inert" attribute is finally coming to the web
- APIs to generate random user avatars
- How to match HTML elements with an indeterminate state
- How to align the text of the last paragraph line
- Packages with high download numbers that nobody wanted to install
- New in VS Code: Surround code with Snippets
- VS Code supports JSDoc-powered type checking
- A look at the dialog element's super powers
- Readable JavaScript conditions
- Array.prototype.reduce's initial value is optional
- Google displays table of contents and anchor links
- reportError – a method to report to global event handlers
- You can't override !important user agent CSS declarations
- Emojis and cultural differences
- Coding in the cloud – CodeSwing on github.dev
- How to preserve separators in the result of String.prototype.split()
- Multiline mode in JavaScript regular expressions
- JavaScript numeric separators are cross-browser supported
- How to override your dependency's dependencies (Node.js)
- An extension to boost your VS Code JavaScript productivity
- New on the web: programmatically open a native date picker
- rcmd – an alternative to "active app tabbing"
- Different background animations on mouseenter and leave
- TLDraw – keyboard-first annotations on your screen
- Filter and map Array values with a flatMap one-liner
2021 76
- Recursive directory creation with shell brace expansion
- How to hide Microsoft Edge's password reveal button
- Code golfing at its best
- hwb() – a color notation for humans?
- Why accessibility design should be a thing
- How to define your relationship to sites you link to
- "await.ops" – less typing, more promise-handling
- git supports global gitignore files
- A browser extension to make Wikipedia look modern
- What are idempotent scripts?
- Mozilla's positions on all the new web specifications
- Highlights of the Web Almanac 2021
- Three Markdown tricks I just learned
- How to define dark/light mode images in GitHub Markdown
- The surprising behavior of "important CSS custom properties"
- New in CSS: relative colors
- New in JavaScript: Array.findLast and Array.findLastIndex
- How to detect Emojis in JavaScript strings
- A directory-dependent and interactive command history
- How to correctly load SVG favicons
- How to load Medium posts without all the "Medium stuff"
- Every emoji has a very particular meaning, or doesn't it?
- "npm root" locates the global node modules directory
- Cross-origin module scripts require CORS response headers
- How to control the used Gmail account when using slides.new, docs.new, etc.
- Conditional border-radius and three future CSS features
- How to disable Chrome's URL bar autosuggestions
- ARIA in HTML authoring rules
- How to define progressive web app (PWA) screenshots and shortcuts
- Three exciting Chromium DevTools experiments
- CodeSwing – a VS Code extension for quick prototyping
- How to color the browser scrollbar across browsers
- How to use a serverless function as image/caching proxy
- A UI for managing your Node.js dependencies in VS Code
- rgba() and hsla() are legacy functions and aliases in modern browsers
- How to enable beautiful cursive fonts in your VS Code theme
- How to enable semantic highlighting in VS Code
- How to discard tabs to save resources in Chrome, Edge and Firefox
- How to configure VS Code Bracket Colors
- Chrome and Edge provide a highly visible focus outlines
- How to focus an already open browser tab (Chromium and macOS)
- How to apply directory dependent git configuration using conditional imports
- Promises-based timer functions are supported in Node.js 16
- Safari only supports image formats macOS/iOS support, and that's good for some users
- A better way to navigate/search your CLI history – McFly
- Can we have custom media queries, please?
- How to extract text from an image via the CLI
- User preference feature queries have a boolean context
- How to detect media query support
- Automatic hyphenation depends on the defined document language
- An SVG filter to pixelate images
- A VSCode extension to understand function parameters
- How to access the your sites' Google cache from the URL bar
- A natural shadow with SVG filters
- How to run apps in low-resolution on macOS
- How to run copied CLI commands with a leading "$" sign
- Multi-colored text in CSS
- Input-wrapping labels are not supported by Dragon
- Mobile Safari doesn't zoom into form inputs with minimum 16px
- How to visualize the tab order without using an extension in Firefox
- How to find all internal pages in Chromiums and Firefox
- How to import JSON files in ES modules
- CSS defines color values that follow system preferences
- How to add a directory but ignore included files in git
- How parameter expansion helps to not accidentally delete all the files on your machine
- A custom "dev" command with auto-completion
- How to import JSON files in ES modules (Node.js)
- How to start using all the aliases you set up (and forgot)
- CSS "inset" is supported across all major browsers
- How to define Open Graph / Twitter image alt text (and why it might not matter...)
- Firefox support selection of multiple text areas
- Should DevTools teach the CSS cascade?
- A CSS-only typewriter effect
- How to disable scaling for stroke width
- How to read an entire document using VoiceOver
- How to style radio and checkbox inputs with accent-color