# shaunchander.me > Pragmatic, systems-driven product engineer in Brooklyn. I write about systems, the tools I use, and the strange route from clinic to codebase. ## Writing - [Form validation with Zod and Svelte](https://shaunchander.me/writing/form-validation-with-zod-and-svelte): Let's learn how to implement solid form validation with Zod and Svelte, two of the coolest frameworks in web dev right now. ℹ️ This post assumes that you use Svelte with… (2023-05-23) - [Effective modals in SvelteKit](https://shaunchander.me/writing/effective-modals-in-sveltekit): Let's learn how to build effective modals in SvelteKit. I actually ran head-on into this problem for an app I'm building. I'll explain a bit below what the problem is and why it's… (2023-05-22) - [Client-side only middleware in SvelteKit](https://shaunchander.me/writing/client-side-only-middleware-in-sveltekit): I'm building a SPA with SvelteKit and came across a need to add some middleware (for authentication purposes) to the app. Now, in SvelteKit, we have this concept of a function,… (2023-05-07) - [Up and running with Turborepo (feat. NextJS and SanityCMS)](https://shaunchander.me/writing/up-and-running-with-turborepo-feat-nextjs-and-sanitycms): (2023-04-12) - [Building animated mobile navbars with framer-motion and TailwindCSS](https://shaunchander.me/writing/building-animated-mobile-navabars-with-framer-motion-and-tailwindcss): In this video you'll learn how to add more creative flair to your project with a fully animated mobile navbar! (2023-04-09) - [Remove an outer array in JavaScript with the flat method](https://shaunchander.me/writing/remove-an-outer-array-in-javascript-with-the-flat-method): The other day I was working on Milk Road's NFT page and one issue I was running into was rendering rows of data while using TanStack Query's hook. For those that don't know, will… (2023-03-04) - [Tip #32: Improve images by using the picture tag](https://shaunchander.me/writing/improve-images-by-using-the-picture-tag): In the previous tip I talked about optimizing your images using the attribute. Continuing with the theme, I want to talk about using a newer HTML tag called to build… (2023-02-25) - [Tip #31: Improve image performance by using lazy loading](https://shaunchander.me/writing/improve-image-performance-by-using-lazy-loading): Performance means everything in creative web design and one of the best ways to start with performance conscious design is to optimize your images. Images are single-handley the… (2023-02-25) - [Tip #33: Automatically add ellipsis with the truncate utility](https://shaunchander.me/writing/automatically-add-ellipsis-with-the-truncate-utility): When working with large blocks on text on the frontend we sometimes want to truncate that text with an ellipsis (the three ). Taking something like this: and turning it into: This… (2023-02-25) - [Tip #28: Use containers properly in TailwindCSS with padding](https://shaunchander.me/writing/use-containers-properly-in-tailwindcss): In a previous tip, I wrote at a high level why you should use containers and paddings to build responsive websites. This time around, I want to get a bit more technical with how… (2023-02-24) - [Tip #30: Make your external links secure with the rel attribute](https://shaunchander.me/writing/make-your-links-secure-with-the-rel-attribute): Did you know that your carry inherit security risks? It's kinda weird but it's true, a naked tag that doesn't define a attribute is considered "unsecure" by the Google Lighthouse… (2023-02-24) - [Tip #29: Debug your CSS with a ??? utility](https://shaunchander.me/writing/debug-your-css-with-a-utility): In JavaScript we can easily debug our code using . Unfortunately, we don't have a function in CSS, but that doesn't mean we can't build something with a similar functionality. In… (2023-02-24) - [Tip #26: Use clamps to build fluid typography systems](https://shaunchander.me/writing/use-clamps-to-build-fluid-typography-systems): Fluid typography is one of those concepts in web design that I feel like is still in its infancy. Not many people know about or use it but it's actually among the most powerful… (2023-02-23) - [Tip #25: Fix z-index issues using relative positioning](https://shaunchander.me/writing/fix-z-index-issues-using-relative-positioning): One of the most annoying things in HTML/CSS is bug-fixing a z-index issue. Lucky for you, I'll show you an effective trick to fix z-indexing 99% of the time and it's actually… (2023-02-23) - [Tip #27: Build simple sliders with scroll snapping in TailwindCSS](https://shaunchander.me/writing/build-simple-sliders-with-scroll-snapping-in-tailwindcss): You know those flick sliders you see on mobile? The ones where you kinda just swipe and the slider snaps to the next element in the container? (this is all native CSS by the way)… (2023-02-23) - [Tip #24: Use arbitrary variants in TailwindCSS to style headless CMS content](https://shaunchander.me/writing/use-arbitrary-variants-in-tailwindcss-to-style-headless-cms-content): Got a bunch of raw HTML coming in from a headless CMS. Want to style all of it with TailwindCSS only? Don't want to use an extra CSS file? Introducing TailwindCSS's arbitrary… (2023-02-22) - [Tip #22: Build price tables with flex-box](https://shaunchander.me/writing/build-price-tables-with-flex-box): Let's learn how to build stellar price tables in TailwindCSS using flex-box. Price tables are an awesome way to quickly learn and master flex-box for those just starting our in… (2023-02-22) - [Tip #23: Always define width and height attributes for images](https://shaunchander.me/writing/always-define-width-and-height-attributes-for-images): When working with images on the web, it's extremely important that you define the and attributes on that image if you know its size before-hand. Here's why. Let's say we're… (2023-02-22) - [Tip #20: Use transforms to build wavy section dividers](https://shaunchander.me/writing/use-transforms-to-build-wavy-section-dividers): Wavey section dividers add a lot of creative flare to a landing page! I personally use haikei.app to generate the waves for use on my websites. fffuel.co is also a great resource… (2023-02-21) - [Tip #19: Use containers and padding to build responsive websites](https://shaunchander.me/writing/use-containers-and-padding-to-build-responsive-websites): Making websites responsive is a skill learned through repetition and experience. Over the years, I've learned that a key aspect of making a website responsive is to use max-width… (2023-02-21) - [Tip #21: Add confetti effects to your website with confetti.js](https://shaunchander.me/writing/add-confetti-effects-to-your-website-with-confetti-js): One of the best effects on the web today is a burst of confetti that gets triggered when a user clicks a button or completes a task. You can very easily add your own confetti… (2023-02-21) - [Tip #17: Use the scroll-behavior property to set smooth scrolling](https://shaunchander.me/writing/use-the-scroll-behavior-property-to-set-smooth-scrolling): Back in the old days, I used to use a jQuery script for adding smooth-scrolling to anchors on my websites. Nowadays, we have a native CSS property that can do that for us (hooray… (2023-02-20) - [Tip #16: Use article tags correctly](https://shaunchander.me/writing/use-article-tags-correctly): I talked a bit before about semantic HTML and why using it is good for SEO. Today, I'm introducing a new semantic HTML tag: . The tag is supposed to be used whenever you're… (2023-02-20) - [Tip #18: Add TailwindCSS to any project with npx](https://shaunchander.me/writing/add-tailwindcss-to-any-project-with-npx): Let's say your working on a custom boilerplate or you have an older project that needs a migration and you want to use TailwindCSS. You can very easily add TailwindCSS to any… (2023-02-20) - [Tip #13: Use Date to add the current year to your copyright claim](https://shaunchander.me/writing/use-date-to-add-the-current-year-to-your-copyright-claim): Typically at the bottom of websites you'll see something along the lines of "© Website Name 2023. All Rights Reserved". While you can hard-code this piece of content in your… (2023-02-17) - [Tip #14: Change the text highlight color with ::selection](https://shaunchander.me/writing/change-the-selection-color-using): Try highlighting this text. Notice how, by default, the browser applies a sort of blue-ish tint as the background color? You can actually customize what this background color is… (2023-02-17) - [Tip #15: Build buttons using inline-flex](https://shaunchander.me/writing/build-buttons-using-inline-flex): Button-building is somewhat of an art and certain people have certain preferences on how to build a good, re-usable button component. Today I want to highlight my method for… (2023-02-17) - [Tip #10: Use divides in TailwindCSS to quickly add borders](https://shaunchander.me/writing/use-divides-in-tailwindcss-to-quickly-add-borders): Got a list? Want to add borders in between in each item? You can do that really quickly using TailwindCSS's utility. It works similarly to something like this: Except, you don't… (2023-02-16) - [Tip #11: Push elements to the bottom of their containers with flex-grow](https://shaunchander.me/writing/make-card-components-the-same-height-with-flex-box): Picture this: you're working on a price table section that uses cards and each card has a different length list of features and a call-to-action button to purchase the plan below… (2023-02-16) - [Tip #12: Augment your browser console logs with CSS](https://shaunchander.me/writing/augment-your-browser-console-logs-with-css): ℹ️ I built an open-source logging library called leucine that implements what this tip goes over! Check it out if you're interested in a colorful, emoji-first logging experience.… (2023-02-16) - [Tip #8: Use focus-visible to improve keyboard accessibility](https://shaunchander.me/writing/use-focus-within): Accessibility (aka a11y) is a core web vital used by the Lighthouse audit to rank websites accordingly, so its important that the websites we build adhere to the standards… (2023-02-15) - [Tip #9: Disable image drag by setting draggable to false](https://shaunchander.me/writing/disable-image-drag-by-setting-draggable-to-false): Annoyed that your users can drag and save your images offsite? It's actually an intended feature of the browser (and its recommend you keep it enabled for accessability purposes)… (2023-02-15) - [Tip #7: Build grid systems with flex containers](https://shaunchander.me/writing/build-grid-systems-with-flex-containers): It may come as a surprise that I recommend you use flex containers for building the basic 12-column grid system rather than CSS grid. While CSS grid is great for building literal… (2023-02-15) - [Tip #4: Use semantic HTML tags to increase SEO](https://shaunchander.me/writing/use-semantic-html-tags-to-increase-seo): When it comes to writing HTML, I like to think of it as describing the content that's on my page in the best way possible rather than adhering to some sort of standard. This is… (2023-02-14) - [Tip #6: Use focus rings to improve user experience on input forms](https://shaunchander.me/writing/use-focus-rings-to-improve-user-experience-on-input-forms): Working with inputs in HTML and CSS is tough. What's even tougher: adding good user experience. There's many stipulations and pragmatism over how you should style your inputs and… (2023-02-14) - [Tip #5: Use flex columns to create your website's layout](https://shaunchander.me/writing/use-flex-columns-to-create-your-websites-layout): When you're just starting out on a new page, the first thing you want to tackle is the page's layout. This is where everything on your page will live: its navbar, the main… (2023-02-14) - [Tip #3: Add hover effects to SVG icons with fill](https://shaunchander.me/writing/add-hover-effects-to-svg-icons-with-fill): In TailwindCSS, you can very easily add icon hover effects using the utility. Fill is actually a native CSS property that applies coloring into an SVG element's tag(s). Let's grab… (2023-02-13) - [Tip #1: Use space and gap utilities in TailwindCSS](https://shaunchander.me/writing/use-space-and-gap-utilities-in-tailwindcss): Spacing elements with margins and paddings is hard to read and hard to standardize. Instead, use Tailwind's built-in spacing utilities: and . Both utilities let you add spacing… (2023-02-12) - [Tip #2: Create faded background images using linear gradients](https://shaunchander.me/writing/create-faded-background-transitions-using-linear-gradients): Stop using Photoshop to add a gradient on top of your images so you can fade them into background! Instead, let me know show you how you can do it with just HTML and CSS. Start by… (2023-02-12) - [Tailwind Tips — Maintaining global typography styles](https://shaunchander.me/writing/tailwind-tips-defining-global-typography-styles): Have you ever worked on a project in TailwindCSS and thought to yourself: "man... I wonder how I could make typography styling easier". I certainly have. Let me paint you a… (2023-02-06) - [Setting Ghost's admin url properly](https://shaunchander.me/writing/installing-ghost-as-a-headless-cms): This weekend I ran into a particular issue with Ghost where I wanted to have the public URL point to https://shaunchander.me/blog but also have the admin panel accessible on a… (2023-02-05) - [All about variants in framer-motion](https://shaunchander.me/writing/all-about-variants-in-framer-motion): If there's one feature that makes framer-motion an absolute kick-ass framework, it's variants. Variants are among the most powerful animation tools for frontend development. What… (2023-01-23) - [Coming back after a break](https://shaunchander.me/writing/coming-back-after-a-break): So... I've been out for a bit (so much for daily posting, \insert why god meme here\). It was a for a good reason though, I recently moved into a new place! I've been spending the… (2023-01-17) - [Building animated mesh gradients with whatamesh](https://shaunchander.me/writing/building-animated-mesh-gradients-with-whatamesh): Mesh gradients look awesome. There's just something subtle and calming about the way the colors and shadows blend together to create an illuminating background. I really like the… (2023-01-06) - [Enter and exit animations with framer-motion](https://shaunchander.me/writing/all-about-animatepresence-in-framer-motion): ℹ️ Hey this is Part 3 of my series on getting started with framer-motion, check outs Part 1 or Part 2 if you haven't already. One of framer-motion's coolest features is the… (2023-01-04) - [Gesture animations with framer-motion](https://shaunchander.me/writing/gesture-animations-with-framer-motion): This is Part 2 of my framer-motion series. Take a peek at Part 1 if you need an introduction to framer-motion. ... Gestures? It might sound really weird at first but gestures are… (2023-01-02) - [Get started with framer-motion](https://shaunchander.me/writing/getting-started-with-framer-motion): framer-motion - it's probably that one React framework you always promise you'll learn over the weekend and that this time you'll definitely do it but something pops up or you see… (2023-01-01) - [A lot happened in 2022](https://shaunchander.me/writing/2022-was-great): 2022 was one of my wildest years on paper. I graduated college, launched a startup, broke an ankle, and joined a team as a fulltime frontend engineer. Just a year ago, I was… (2023-01-01) - [My stack going into 2023](https://shaunchander.me/writing/my-stack-going-into-2023): It's the new year 🎉 And that means we get a whole new cycle of JavaScript frameworks popping into (and out of) existence. In retrospect I'd say 2022 was the most eventful year… (2022-12-31) - [Actually update npm packages to their latest versions](https://shaunchander.me/writing/how-to-actually-update-npm-packages-to-their-latest-versions): So the other day I was working on updating packages for our repo over at Bitfo and just like a standard NodeJS developer would do, I ran the following command: It spit out a list… (2022-12-31) - [So... I built my website with QwikJS](https://shaunchander.me/writing/so-i-built-my-personal-website-with-qwikjs): QwikJS. It's a new JavaScript framework that's fast. Hella fast. In fact it's so fast that it might just be the end all be all of JAMStack frameworks. It's currently in… (2022-12-30) ## Pages - [About](https://shaunchander.me/about): Long-form bio, work, bookshelf, talks, setup. - [Writing archive](https://shaunchander.me/writing): Filterable index of all 51 essays. ## Machine-readable mirrors - Every HTML page has a .md sibling at the same URL (e.g. https://shaunchander.me/about.md). - Every post has a JSON-LD endpoint at /writing/.json.