All blogs / JavaScript / TypeScript
Zell Liew
Browse 482+ articles on web development, JavaScript, CSS, and more. Step-by-step tutorials and insights from over a decade of building for the web.
- Posts
- 482 from 23 Mar 2013 to 10 Oct 2026
- Posting
- weekly (45 in the last year)
- Kind
- personal blog
- Feed
- https://zellwk.com/rss.xml
2026 45
- Redefining My Relationship With You
- The omitEmpty Function
- Speaking Without Inhibition
- Sharpen The Saw — Only 3 Mins
- The Circle Of Influence
- Be Grateful, But Not Overly Grateful
- The Walking Stick On The Journey
- Help, Or Don't
- Hard Skills, Soft Skills, And Money-Making Skills
- Unblocking My Publishing
- The Infinite Game of Blogging
- I've Built an AI Clone That Works!
- Building Responsive Layouts Without Writing More CSS
- The State of Tech Education in the AI Age
- Building a Real Blog Easily in Astro
- Two Wrongs Don't Make a Right
- Four Ways to Deal with Claude's Reduced Usage Limits
- Worst Enemy
- Experimenting with a different way to write
- Unorthodox Tailwind is live!
- Enhancing Astro With a Markdown Component
- Markdown + Astro = ❤️
- Disable Sounds in VSCode
- Giving Myself an A for 2026
- Anchor Habits
- Eliminating MCP Token Costs in Claude
- I Used AI to Lose Weight (And It Worked)
- Skip the Import — A Simpler Way to Use Images in Astro
- 4 Reasons That Make Tailwind Great for Building Layouts
- Soul-Sucking vs Soul-Enriching
- Perceiving Hope in a Hopeless State
- Accepting What You Reject
- Popover API or Dialog API: Which to Choose?
- The Cause of Depression
- Distinguishing "Components" and "Utilities" in Tailwind
- Public Therapy
- Ditching the Eisenhower Matrix
- Publishing a Coding Theme
- Building a VSCode Theme
- Everyone Loves This!
- There is No Need to Trap Focus on a Dialog Element
- If and Not Components for Astro
- Closing off the reflections about 'violence'
- Time doesn't heal wounds
- Year End Review — 2025
2025 23
- Building a Honeypot Field That Works
- Composition in CSS
- We Might Need Something Between Root and Relative CSS Units for “Base Elements”
- Thinking Deeply About Theming and Color Naming
- Making a Masonry Layout That Works Today
- A Primer on Focus Trapping
- Using CSS Cascade Layers With Tailwind Utilities
- A Better API for the Intersection and Mutation Observers
- A Better API for the Resize Observer
- Streaming capabilities comes to zlFetch
- Making sense of starting-style
- So, You Want to Give Up CSS Pre- and Post-Processors…
- Tailwind’s @apply Feature is Better Than it Sounds
- Setting up a Corne Keyboard v4
- Upcoming Breaking Changes for Splendid Layouts
- A little rant about breaking changes
- Division of topics
- How to stay sane when your partner is in a depressive rut
- Feeding the wrong wolf
- Compass, Path, and Journey
- Reflections on highlighting my violence
- Convincing doesn't work
- I called the suicide hotline for my wife
2024 41
- Don't try to make anyone happy
- Killing and Restarting pm2
- Forcing the future
- Clarifying the Relationship Between Popovers and Dialogs
- It sucks. What sucks?
- Tooltip Best Practices
- Everyone becomes a sellout at some point
- Solving Background Overflow With Inherited Border Radii
- Understanding Recursion in JavaScript
- You can’t write like Seth Godin
- Best Practice for Astro Endpoints
- Stress for Metamorphosis
- How to be good enough
- Busyness
- Speed of Svelte reactive bindings vs keyboard events
- Conditional Slot Forwarding is not a thing in Svelte 4
- Breaking out of Svelte's reactive statements
- What developers should be learning
- A Great Failed Experiment
- Data Table Accessibility in 2024
- Found the Light
- Collecting Payments with Stripe while using Astro
- Easy way to remove inline styles
- Understanding and using npm exports
- DoItAnyway
- Invisible adversaries
- No more waiting
- 4 years is not too many
- Handling cookies with Fetch's credentials
- Using Cookies vs Local Storage for storing access tokens
- Bravery
- Move fast, break things
- JavaScript Mental Models
- Why I love the web
- Analytics and Ads
- An easy way to implement conversion tracking for Facebook
- On Spam
- Splendid Layouts in here!
- Splendid Layouts
- My CSS of Late
- 3 Techniques to learn JavaScript effectively
2023 31
- Changing CSS Variables with Tailwind
- The main challenge of building an Astro-first component library
- Enough of the homogenous and soulless content all around the internet
- The easiest way to get and set CSS Variables in JavaScript
- December 2023
- The easiest way to get __dirname in Node with ES Modules
- The easiest way to use SVGs in an Astro or Svelte app
- Automatic reactivity with Vanilla JavaScript with two methods — Getters and Setters and JavaScript Proxies
- Iterating over objects in JavaScript
- Easy way to parse JSON with JavaScript
- Free chapters for Magical Dev School
- Making a nice neon button
- Splendid Astro Spacing — A Tailwind Utility for Astro
- Updates for Understanding Async JS and Rest APIs
- Easy caching on the local file system with Node
- zlFetch now supports FormData!
- Limitations of Scoped CSS
- Quality of life improvements for zlFetch
- The Magical Dev School Student Portal is live!
- Finding my roots in my business
- How to get better at design (for developers)
- Here’s how to quickly test components that use container queries
- When building components in Astro, you might not want to use Astro files
- Best practices for container queries
- Overcoming styling frustrations caused by Astro islands and slots
- How AI will shape the coding ecosystem in the future
- Convertkit API: Using Forms vs Tags
- Building fancy list items in Astro
- The Spirit of CSS Tricks is now gone
- How camel-cased classes are way better than kebab-cased classes
- Rendering MDX in a Svelte component when using Astro
2022 18
- Setting up Visual Studio Code for Web Development — For Beginners and Intermediate Developers
- Never let anyone stop you from pursuing your dreams
- Understanding the color-scheme property
- Using npm packages in the frontend without any bundlers
- Best way to install Node and keep it up to date
- Understanding CSRF Attacks
- How to find a tag id in Convertkit
- A library to make localStorage easier to use
- New CSS Color syntax — rgb instead of rgba
- Don't be ashamed of tutorial hell
- Getting a cookie's expiry value on a server
- Rsync with a custom port
- Rsync with Github actions when using a a custom port
- Why I stopped using Operator Mono
- Using async/await in Express
- Serving HTTPS locally with Node
- Get good at the hiring game
- Year end review — 2021
2021 18
- Dealing with anxiety during job interviews
- Why I'm super excited about Astro (a new static site generator)
- How and when to use Async and Defer attributes
- Trying Your Best is really bad advice (and strategy)
- Rapid Mac Setup for Frontend Development
- Using Gulp with Dart Sass
- Disabling languages for Prettier (in VScode)
- Prettier and Standard in VSCode
- How to remember JavaScript
- Overcoming 7 main problems of learning to code for people who don't have a developer job
- 8 lessons I learned from spending 4 years writing one course — Learn JavaScript
- How to debug a Github Actions' secret
- Deploying to a server via SSH and Rsync in a Github Action
- Understanding how to use Github Actions
- How to use Reduce in JavaScript
- Choosing between Netlify, Vercel and Digital Ocean
- How to write super simple and useful regular expressions for the real world
- Year End Review — 2020
2020 44
- Case Conversion in JavaScript
- How I set up my Moonlander
- Why we should use Ergonomic keyboards
- What's the difference between an Interface and an API?
- Understanding JavaScript Prototype
- Testing JavaScript Performance
- Leading Trim is in the works!
- A JavaScript Utility Library?
- How to improve without receiving feedback
- How to create sites with winding SVG paths
- Giving away 99 copies of The Coding Career Handbook by Shawn Wang
- TCC: The course that gave me the strength to pursue my dreams
- Why use Getters and Setters functions
- Creating a deep-assign library
- Copying properties from one object to another (including Getters and Setters)
- Getting the horizontal and vertical centers of an element
- Polymorphism in JavaScript
- Arrow Function Best Practices
- Getting CSS Translate values with JavaScript
- How I work with arrays
- Snowpack + Eleventy + Sass + PostCSS
- First look at Snowpack
- Customised (and effective) Visual Studio Code keyboard shortcuts for Mac and Windows (Part 2)
- How to think like a programmer
- Customised (and effective) Visual Studio Code keyboard shortcuts for Mac and Windows
- Syncing Visual Studio Code settings between Mac and Windows
- Bash vs Zsh vs Fish
- Preventing a Windows PC from adjusting the screen's brightness automatically
- Emulating Mac's Dvorak-Qwerty-⌘ on Windows
- Build Your Developer Brand post-mortem
- Free Workshop on Branding and Marketing yourself as a developer
- Building a Simple CRUD app with Node, Express, and MongoDB
- Setting up Windows for web development
- A Simple CLI for Convertkit
- Element.focus vs aria-activedescendant
- Overcoming my panic towards accessibility
- Designing Learn JavaScript's course portal (Part 3)
- Designing Learn JavaScript's course portal (Part 2)
- Installing MongoDB on Mac (Catalina and non-Catalina)
- Designing Learn JavaScript's course portal
- Building a login system with HTML, CSS, and JavaScript
- Getting keyboard-focusable elements
- Multi-line gradient links
- Year-end review: 2019
2019 47
- Mongoose 101: Population
- Mongoose 101: Working with subdocuments
- Mongoose 101
- What to do if you're struggling with a Bootcamp
- Understanding Homebrew
- Protecting and syncing secret keys
- Handling Errors in Express
- What programming languages should you learn?
- The difference between HTML, CSS, and JavaScript
- Style hover, focus, and active states differently
- Creating a custom focus style
- Designing a focus style
- Converting callbacks to promises
- Three useful Express middleware
- Inconsistent behavior among browsers when clicking on buttons
- Dancing with Fear
- Seeding a database
- Connecting Jest and Mongoose
- Endpoint testing with Jest and Supertest
- How to setup a local MongoDB Connection
- Frontend vs Backend
- How to add Flexbox fallback to CSS Grid
- How to build a calendar with CSS Grid
- Stages of learning
- Shutting down Fridays with Zell
- Everything You Need to Know About Date in JavaScript
- Using Standard with VSCode
- How to go through the job application process—an interview with Chris Lienert
- On Advocacy
- Maybe we should step away from the online-world for a bit
- Dealing with nested callbacks
- JavaScript async and await in loops
- A new (and easy) way to hide content accessibly
- JavaScript async and await
- Publishing packages that can be used in browsers and Node
- How to ignore files from your npm package
- The best time to npm init
- How to publish packages to npm (the way the industry does things)
- How to use JSDelivr
- My CSS reset
- Migrating to a new Mac
- Setting up my new Mac (Part 1—the apps I use)
- RSS and Tags are here!
- Zellwk.com is now open source!
- It's okay to write dirty code
- Sit down and figure it out
- Using small pockets of idle time
2018 87
- Year end review—2018
- Checking if an input is empty with JavaScript
- Checking if an input is empty with CSS
- The Gitignore file
- Why support older browsers?
- What not to save into a Git repository
- Supporting older browsers—Part 3: JavaScript
- Undoing changes in Git
- Supporting older browsers—Part 2: CSS
- Git Tags
- Supporting older browsers with Polyfills
- Switching to Dvorak as a web developer
- How to take a good break
- How to review and edit a pull request
- Getting out of a productivity funk
- How to submit a pull request
- Creating a simple form with CSS Grid
- How to use Git stashes as a temporary storage
- Creating a simple form with Flexbox
- How I remember CSS Grid properties
- Semantic Versioning
- Becoming more productive while working less
- Managing your Git branches with Git Flow
- When will Learn JavaScript be completed?
- What is a branch in Git?
- Changing my refund policy
- Resolving Git conflicts
- How to use the :empty selector and the :blank selector
- Cloning a Git repository
- What makes a good frontend developer?
- Pulling from a Git remote
- Stop using big words and industry jargons (and what to do instead)
- Pushing to a Git remote
- Creating good analogies
- Your first Git commit
- How to write a good coding article
- Setting up a Git Client
- The key to teaching
- Starting a podcast
- Where to find people to teach
- Visual Studio Live Share
- What to do when life shits on you
- Finding mentors
- How to get CSS values in JavaScript
- Finding motivation
- Finding the right materials to learn
- Why you shouldn't reassign values in JavaScript
- Dealing with overwhelm
- Why you learn when you teach
- Dealing with confusion
- 5 things I learned from Infinity Wars
- Which JavaScript framework should you learn?
- Finding time to learn
- Which should you learn first? Frameworks or JavaScript?
- Results of the restructure
- How I'm going to teach authentication
- New CSS features that are changing web design
- Is your code good enough?
- Should I teach authentication in Learn JavaScript?
- Are you a real developer?
- Avengers, Star Wars, and learning code
- Why I switched from Sublime Text to Visual Studio Code
- My experience at CSS Conf China
- Why I restructured Learn JavaScript
- Traversing the DOM with JavaScript
- How to handle the "bad experience" question
- How to build a calculator—part 3
- Job search protip—don't look for a junior position
- How to build a calculator—part 2
- Are you too old to learn to code?
- How to build a calculator—part 1
- Experiment publicly
- Case study—a project from hell
- How do you decide what to build?
- How to use a linter
- Responsive Vertical Rhythm with CSS Custom Properties and CSS Calc
- Useful VS Code keyboard shortcuts
- Setting up Visual Studio Code (Part 3)—Extensions
- Faux Subgrid
- Intro to Object Oriented Programming in JavaScript
- Setting up Visual Studio Code (Part 2)—HTML, CSS and JavaScript settings
- Setting up Visual Studio Code (Part 1)—appearances
- Year End Review—2017
- Understanding And Using REST APIs
- Should you use CSS or JavaScript for animations?
- Why mutation can be scary
- Can I get a discount?
2017 39
- An introduction to animations with Greensock Animation API (GSAP)
- CSS Animations explained
- Dealing with Imposter Syndrome
- CSS Transitions explained
- How to make interactive components
- Understanding for loops
- Understanding if/else statements
- How to debug Javascript errors
- Learning JavaScript – where should you start and what to do when you're stuck?
- Console.log everything!
- Understanding JavaScript Functions
- Should you use semicolons in JavaScript?
- What are variables and why use them in JavaScript
- Announcing Learn JavaScript!
- How to overcome your fear of JavaScript
- How to get hired as a junior web developer
- Typi—case study
- JavaScript Scope and Closures
- Should you use this in JavaScript?
- Remembering what you learned
- 5 top tips for speedy learning
- This in JavaScript
- Promises in JavaScript
- Callbacks in JavaScript
- How to set up your development environment to learn JavaScript
- The rules of responsive web typography
- Introduction to commonly used ES6 features
- Using Fetch
- Altering the DOM with JavaScript
- Breaking the rules
- Writing modular CSS (Part 3) — CSS file structure
- 20 things to consider when creating your first Node.js application
- Writing modular CSS (Part 2) — Namespaces
- Writing modular CSS (Part 1) — BEM
- Should you learn [insert shiny new tool]?
- How to pair typefaces
- Fighting decision paralysis
- How to read faster and remember more
- Year End Review – 2016
2016 23
- How to build a responsive grid system
- Designing grids
- Don't reinvent the wheel
- Learning to code quickly
- How to Reset Susy's Span or Gallery
- How to Ask Good Coding Questions That Get Great Answers
- Everything about the Modular Scale Sass Libary and Modular Scale with Typi
- Changing Modular Scale Ratio at Different Breakpoints
- Responsive Modular Scale
- Were We Wrong About Vertical Rhythm All Along?
- Deploying a Static Site with Cron and Git
- Advanced Usage with Typi
- An In-depth Tutorial to Typi
- Beating Procrastination
- Moving from HTML Grid Systems to CSS Grid Systems
- Is Web Typography Completely Broken?
- PX, EM or REM Media Queries?
- Viewport Unit Based Typography
- Why is Vertical Rhythm an Important Typography Practice?
- REM vs EM – The Great Debate
- Star Rating Re-imagined with Flexbox
- Everything I know about Responsive Web Typography
- Year End Review – 2015
2015 21
- Animating SVGs (CSSConf.Asia talk)
- Trolls & Expert Opinions – Lessons Learned From Publishing on a Popular Website
- Website Layout Tools Compared—Flexbox Vs. Susy
- Overcoming Your Fears
- Migrating From Bootstrap to Susy
- What to add to your Gitignore File
- How to Modularize HTML Using Template Engines and Gulp
- Gulp for Beginners
- A Gulp.js Tutorial (Part 2)
- A Gulp.js Tutorial
- Choosing a Build Tool
- Overcoming your Fear of the Command Line
- Manage your Frontend Dependencies with Bower
- An Overview of a Development Workflow
- Common Problems With Susy Gallery And How To Solve Them
- Why I stopped blogging, and what do you want to read about next?
- How to use Masonry with Susy
- Mappy Breakpoints, A Breakpoint Mixin that uses Sass Maps
- Configuring Gulp to use LibSass with Susy
- Configuring Grunt To Use LibSass With Susy
- Learning Susy Update Is Going To Be Delayed
2014 30
- How To Write Mobile-first CSS
- How to use susy with bootstrap
- I'm Going To Make The Learning Susy Book Better, And What That Means For You
- Fix 90% of Your Problems With Susy by Getting This One Concept Right
- How I Wrote and Sold My First Ebook (and how you can do it too)
- How to Create Off Canvas Layouts with Susy
- Build Web Layouts Easily with Susy
- How to Build a Responsive Website That Supports Older Browsers
- Smarter Layouts with Susy
- Bootstrap’s grid system vs. susy—a comparison
- Creating Asymmetric Layouts With Susy
- Understanding Gutter Positions in Susy
- How to Debug Your Susy Layout with the Susy Background Image (Even If The Grid Changes)
- Organizing Multiple Theme Styles with Sass
- A Sexier Float Label Pattern
- Compass vs Autoprefixer
- Using Codekit 2 Autoprefixer With Compass
- Neatly Organized Layouts with Sass Maps and Susy
- Static Grids with Susy 2
- A Complete Tutorial to Susy 2 (Part 2)
- A Complete Tutorial to Susy 2
- A Complete Guide to @font-face
- How to structure HTML for an actual website (Part 2)
- How to structure HTML for an actual website
- Understanding and Using CSS Positions
- How to use Mailchimp API in Wordpress
- Compass Vertical Rhythms
- Understanding CSS Box Sizing Property
- Understanding Wordpress Actions and Filters
- How to find the Wordpress CSS File
2013 15
- How to Quicken Wordpress Development with Grunt JS
- A Complete Tutorial to Susy (Part 2)
- A Complete Tutorial to Susy
- Tools I use for learning and using colors
- Why color pickers and palettes are bad for you
- Wordpress 101 – 5 critical things you need to know to use Wordpress effectively.
- 5 things you can do to keep learning when things turn unexpectedly difficult
- How to organize and edit your CSS painlessly
- Make your website more professional with 1 simple step
- Creating a clean and simple website (Part 3 - Style the content and 6 items to take note)
- Creating a clean and simple website (Part 2 – Styling the header)
- 9 Important CSS Properties You Must Know
- Creating a clean and simple website (Part 1 – HTML)
- The Layout of a Website
- Why I started learning about web design and how you can do it too