I Tried Borders for Tables in CSS — Here’s What Actually Works

I’ve styled more tables than I’d like to admit. Menus, grade sheets, bug lists, even my kid’s soccer stats. And you know what? Table borders can look clean and tidy… or like a spreadsheet from 1998. I’ve done both. Let me explain what worked for me, with real code I used on live pages. For the full blow-by-blow version of the experiment, you can check out the original write-up on CSS Menu Tools.

Quick take: the good, the bad

  • Good: fast, clear, easy to read
  • Good: prints well if you set colors right
  • Bad: double borders can show up if you miss one tiny rule
  • Bad: thick borders look loud on phones
  • Weird: rounding corners with collapsed borders can act fussy

If you ever need to build a side-by-side comparison table—say, evaluating different discreet-dating platforms for an article—the data can get pretty personal and nuanced. I once mocked up a chart using pros, cons, and membership costs pulled from this thorough Ashley Madison review that dissects everything from pricing tiers to privacy features, making it a goldmine of structured info you can plug straight into a polished grid.

Following that project, I pulled together another dataset for a regional sugar-dating overview. The most interesting source was a Chandler-specific piece—check out this in-depth look at Sugar Baby Chandler which lays out local arrangement expectations, cost breakdowns, and safety tips, making it the perfect pool of well-organized facts to drop into a demo table and test out advanced border styles.

For an instant playground to experiment with menu-style borders and live previews, I sometimes hop over to CSS Menu Tools and tweak settings before pasting them into production.

Alright, let’s build from simple to nice. For a broader refresher on table aesthetics, MDN’s step-by-step guide to styling tables with CSS is a handy companion.


The classic “grid” that just works

… (rest of article unchanged)

I Went Hunting For Nutrition Site CSS Inspo — Here’s What I Loved (and What Bugged Me)

I’m Kayla. I design and tinker with front-end stuff. I also eat like a real person who gets busy and forgets lunch. So I spent a week using a bunch of nutrition sites on my laptop and my phone. I took notes on what felt clean, quick, and friendly. I looked at the CSS, the colors, the flow, and those tiny bits that make a page feel calm or loud.

(For an even deeper dive into how I ran that hunt, here’s the expanded case study on my nutrition site CSS inspo adventure.)

I made breakfast in between, and, yes, I did spill coffee on my trackpad. Twice. Anyway, here’s what stuck.

Healthline Nutrition — Calm Greens, Good Bones

I read three Healthline nutrition guides and a few recipe pages on my iPhone 13 and a 13-inch laptop. If you want to see their design celebrated in full, the Healthline Transform case on Awwwards is a great quick look. The vibe feels like a deep breath. Soft greens and blues. A lot of air. Clear type. They use pill badges for things like “medically reviewed.” The badges sit high in the visual stack but don’t shout. I like their section spacing too. It follows a simple step rhythm. Small gaps for tight bits. Big gaps for new ideas. It helps your eyes rest.

  • What I’d borrow: pill badges for facts, soft green accents, and that steady spacing scale. Also their callout boxes with a thin border and a pale tint. Feels safe and smart.
  • What bugged me: the sticky share bar got in the way on my small phone screen. It nudges content when I scroll. Tiny thing, but it adds friction.

CSS note: this is a “less is more” layout. Neutral gray body text. A strong H2 line-height. Buttons with a modest radius, not bubble-y. Shadows stay shy.

Examine.com — Nerdy, Clean, and So… Readable

I live on Examine for supplement and nutrient research. On desktop, they have a tidy table of contents stuck to the side that tracks where you are. The accordions fold up long sections without the “boing” effect. Nice restraint. They also group tags into soft little chips with subtle borders. It looks serious but not stiff.

  • What I’d borrow: sticky table of contents with calm highlight states, accordion sections with clear focus outlines, and a thin progress bar along the top for “how far you’ve read.”
  • What bugged me: sometimes the contrast on secondary links feels a hair too faint. Gray-on-gray is easy on the eyes, sure, but I like a touch more snap.

CSS note: the reading progress bar is a simple, useful pattern. Keep its height tiny. Keep motion gentle. Respect reduced-motion settings, because not everyone wants animation.

MyPlate (USDA) — Big Blocks, Bold Colors, Very Clear

I used MyPlate to explain labels to a friend who’s new to cooking. It reminds me of the clean, blocky layout showcased in the Diet & Nutrition Health Center template that floats around on Behance for similar projects. The color coding helps a lot. Icons are plain and bright. Buttons are chunky with strong labels. The “nutrition label” style graphics are the star. Black border. Bold section headers. It feels like the real food label, but readable on a phone.

  • What I’d borrow: the FDA-style label component using CSS Grid, bold section dividers, and a clear stacking order. It teaches while it shows.
  • What bugged me: some pages feel a bit heavy, color-wise. Great for clarity, but it can shout on small screens.

CSS note: thick borders, strong typographic scale, and grid rows for calories, macros, and footnotes. Keep the kerning firm so numbers line up.

MyFitnessPal — Chips, Charts, and Quick Wins

I keep MyFitnessPal on my phone. On web, I like their little filter chips for recipes and foods. Scrollable, rounded, easy taps. The macro rings and bars translate well to CSS with simple gradients or conic shapes. The CTAs use a brand blue that stands out against white cards.

  • What I’d borrow: horizontally scrollable chips with overscroll hint, color-coded macro bars, and a sticky bottom action bar on mobile that doesn’t cover text.
  • What bugged me: ad blocks can crowd the content flow. When the page jumps, I lose my place. That hiccup hurts trust.

CSS note: chips need good focus states. A light outline and a slightly darker label work well. Keep shadow soft so they don’t look like candy.

NutritionFacts.org — Green, Video-Forward, and Friendly

I watched two videos and read a transcript. Cards show simple thumbs, clear titles, and tags. The green accent is warm, not neon. The transcript accordion opens fast and doesn’t jitter, which is rare. There’s a donation banner that sticks around. It’s polite but present.

  • What I’d borrow: two-line title clamps on video cards, thin borders instead of heavy shadows, and a button style that looks the same in light and dark tints.
  • What bugged me: the sticky banner can create a tight squeeze on short phones. A “minimize” toggle would help.

CSS note: line-clamp on titles keeps grids tidy. Just give the card enough padding so it doesn’t look cut off.

Precision Nutrition — Long Reads Done Right

I read one of their long guides on my couch, tired and hungry. The page felt easy. Big comfy text. Lots of white space. Pull quotes with a soft left border and a serif twist. FAQs at the end wrap it up neatly. No wild animation. The page trusts the content.
(If you want to nerd out on the nitty-gritty of styling those pull quotes, this rundown of quote CSS designs that actually work is gold.)

  • What I’d borrow: generous line-height, pull quotes with a soft accent, and end-of-article FAQs using large tap targets and gentle chevrons.
  • What bugged me: sometimes the intro is very long. I like it. But I did wish for a small summary box up top.

CSS note: set a max line length that feels like a book. Around 65–75 characters per line keeps your brain calm.

Tiny Patterns I Keep Reusing

Quick tip: when I’m mocking up nav interactions, I often spin up a demo in CSS Menu Tools to sanity-check hover states and responsive breakpoints. It’s also where I first wrestled with overlaying dropdown menus purely in CSS—spoiler: z-index will stab you in the back if you’re sloppy. When I’m experimenting with list thumbnails, I lean on this field test of CSS hover on images inside a list for reminders about what trips up mobile.

  • BBC Good Food: nutrition tables that stack on mobile without turning into a mess. Simple borders. Alternating row tints.
  • Verywell Fit: callout boxes with icons and a soft tone for “expert tip” or “try this.” Great for skim readers.
  • Cronometer: dark theme has strong contrast without glare. That’s hard. Their orange pops, but doesn’t burn.
  • MeetnFuck’s “Uber-for-sex” concept: I was curious how ultra-fast, location-based adult apps design for on-the-go decisions. The breakdown at this Uber-for-sex app roundup shows how tight map overlays, single-thumb CTAs, and minimal forms strip the UI down to the essentials—handy reference if you’re studying real-time matching flows.
  • While sketching more relationship-focused adult niches, I also peeked at the Ontario-specific sugar-dating hub Sugar Baby Ontario, which offers a look at how profile cards, verification badges, and allowance calculators blend discreet pastel palettes with “luxury meets safety” cues—worth visiting if you need inspiration for balancing elegance and conversion-driven UI inside high-trust marketplaces.
  • Whole30: filter chips for recipes are roomy and legible. The spacing is generous, which helps big thumbs.
  • Examine (again): evidence badges that sit next to headings without pulling too much focus. Perfect balance.

For the borders on those nutrition tables, my cheat sheet is this quick hit on what actually works for table borders in CSS.

My Favorite CSS Building Blocks From These Sites

  • A calm green accent, like Healthline, for trust cues and checkmarks.
  • A strict spacing scale (4–8–12–16–24). Reuse it everywhere.
  • An FDA-style nutrition label block with CSS Grid and bold dividers.
  • Scrollable filter chips with clear “selected” states and focus rings

I Tried Header Shadows in CSS. Here’s What Actually Worked.

I’m Kayla. I build sites for real people and real budgets. Last spring, I fixed three headers that felt flat and kind of cheap. A tiny shadow made them feel solid. Funny how one line of CSS can change the mood, right? (Want the extended play-by-play? I put it all in my case study here.)

Let me show you what I used, where it looked good, and where it got weird. I’ll share my exact code, too. Need a quick navigation stub to test your shadows? CSS Menu Tools lets you spin up a menu in seconds so you can focus on the polish. While you’re at it, here’s how I overlay dropdown menus with CSS—handy if your header nav needs to float over hero images.

The Quick Win: Simple Box-Shadow on the Header

This is my go-to. It’s fast. It looks clean. I used it on a school blog with a white header over a white page.

header.site-header {
  position: sticky; /* or fixed */
  top: 0;
  background: #fff;
  box-shadow: 0 2px 8px rgba(0,0,0,0.08);
  z-index: 50;
}

How it felt: light and crisp. The header didn’t scream. It just separated the nav from the page.

When it broke: on a low-end Android, a huge blur made scroll feel choppy. So keep the blur small. I like 2px to 8px spread and a soft alpha.

Only Show the Shadow After You Scroll

A client wanted a flat header at the top, but a shadow once you move. I gave two paths.

Small JavaScript. It’s dead simple and works everywhere.

<header class="site-header">...</header>
<script>
  const header = document.querySelector('.site-header');
  let last = 0;
  window.addEventListener('scroll', () => {
    const y = window.scrollY || window.pageYOffset;
    if (y > 2 && last <= 2) header.classList.add('scrolled');
    if (y <= 2 && last > 2) header.classList.remove('scrolled');
    last = y;
  });
</script>
.site-header {
  transition: box-shadow 160ms ease;
}
.site-header.scrolled {
  box-shadow: 0 6px 18px rgba(0,0,0,0.12);
}

Want to push the effect further with keyframes? I learned a ton from this guide to animating box-shadows—it covers everything from easing tricks to GPU considerations.

No JavaScript version using modern CSS. Worked for me in up-to-date Chrome, Safari, and Firefox.

<header class="site-header">...</header>
<div class="scroll-sentinel"></div>
<main> ...lots of content... </main>
/* Shadow only when .scroll-sentinel is not in view */
.site-header {
  position: sticky;
  top: 0;
  background: #fff;
  transition: box-shadow 160ms ease;
}

body:has(.scroll-sentinel:not(:in-view)) .site-header {
  box-shadow: 0 6px 18px rgba(0,0,0,0.12);
}

.scroll-sentinel {
  block-size: 1px;
}

You know what? The CSS trick felt neat. But I still ship the small JS for older stacks or when teams worry about browser edge cases.

Text Shadow for Big Titles (Use a Light Hand)

On a hero image, plain white text can glow too hard. I soften it with a tiny text shadow. If headline styling is on your radar, my hands-on review of title CSS design (full breakdown) walks through more patterns you can steal.

.hero h1 {
  color: #fff;
  text-shadow: 0 1px 2px rgba(0,0,0,0.35);
  letter-spacing: 0.2px;
}

I used this on a travel site header over a beach photo. It read well on phone and laptop. If you push the blur, it starts to look like a sticker. So keep it tight.

When Your Header Is Transparent: Try Drop-Shadow

Box-shadow sits on the box. If your header has rounded corners or a cutout, filter: drop-shadow can look better.

header.glass {
  position: sticky;
  top: 0;
  background: rgba(255,255,255,0.7);
  backdrop-filter: blur(8px);
  -webkit-backdrop-filter: blur(8px); /* iOS Safari */
  /* A faint border helps on light pages */
  border-bottom: 1px solid rgba(0,0,0,0.06);
  /* No box-shadow here */
  filter: drop-shadow(0 2px 10px rgba(0,0,0,0.10));
}

I used this on a food blog with photos behind the header. It felt “airy,” but still grounded. Small note: backdrop-filter is heavier on older phones. I saw a tiny stutter on a Moto G. Not awful, but it’s there.

Dark Mode Without Tears (Use Variables)

I switch shadow color by theme with CSS variables. It saves time and keeps contrast sane.

:root {
  --header-bg: #fff;
  --header-shadow: rgba(0,0,0,0.10);
  --hairline: rgba(0,0,0,0.06);
}

@media (prefers-color-scheme: dark) {
  :root {
    --header-bg: #101114;
    --header-shadow: rgba(0,0,0,0.50);
    --hairline: rgba(255,255,255,0.08);
  }
}

header.smart {
  background: var(--header-bg);
  box-shadow: 0 4px 14px var(--header-shadow);
  border-bottom: 1px solid var(--hairline);
}

In dark mode, shadows need more alpha, not more blur. That keeps it sharp and not muddy.

Tailwind, Bootstrap, or Plain CSS? I’ve Used All Three

On a small shop site with Tailwind, I just did:

<header class="sticky top-0 bg-white shadow-md z-50">...</header>

Wanted a softer look?

<header class="sticky top-0 bg-white shadow-[0_2px_8px_rgba(0,0,0,0.08)]">...</header>

Bootstrap has classes too (shadow-sm, shadow). Plain CSS still gives me the most control. I mix them as needed.

Performance Notes From Actual Devices

I tested on:

  • iPhone 12, Safari
  • Pixel 7, Chrome
  • A very tired Moto G

For a deeper dive into how box-shadow can impact repaint times and scrolling, the benchmarks in SitePoint’s performance roundup are eye-opening.

What helped:

  • Small blur values (2–8px). Big blurs repaint more.
  • Avoid stacking many shadows on one element.
  • For sticky headers, keep the paint area simple. A soft box-shadow plus a 1px border is usually enough.
  • Turn off heavy drop-shadow on old phones if you can.

What hurt:

  • Box-shadows with 40px blur on a sticky header. Scrolling felt gummy.
  • Backdrop-filter plus huge blur plus PNG logo glow. Pretty, but slow.

Little Accessibility Things I Watch

  • I add a faint 1px border under the header. The shadow then can stay light.
  • Don’t rely only on a shadow for separation. Some users have custom colors.
  • On busy images, text needs a shadow or a subtle overlay to read well.

Here’s a tiny overlay that saved me more than once:

.hero::before {
  content: "";
  position: absolute;
  inset: 0;
  background: linear-gradient(
    to bottom,
    rgba(0,0,0,0.30),
    rgba(0,0,0,0.00) 50%
  );
  pointer-events: none;
}

Debug Tricks I Actually Use

  • I crank the shadow to something wild, like 0 20px 50px rgba(0,0,0,0.5), just to see bounds. Then I tune it back down.
  • I check light and dark mode back to back.
  • I scroll fast on phone. If it janks, I shave blur first.

Three Recipes You Can Paste

Minimal and classy:

header {
  position: sticky; top: 0; background: #fff;
  border-bottom: 1px solid rgba(0,0,0,0.06);
  box-shadow: 0 2px 8px rgba(0,0,0,0.08);
}

Soft “glass” header:

“`css
header {
position: sticky; top: 0;
background:

I rebuilt Tailwind CSS to get more classes. Here’s what happened.

I’m Kayla. I ship front-end stuff for a living. Last week, I hit a wall. I needed more Tailwind classes than my build was giving me. So I rebuilt Tailwind, and yes—made it spit out more classes on demand. Simple idea. Not always simple in practice.
If you want the blow-by-blow of that reconstruction, I wrote it up in detail in this post.

You know what? It was worth it.

My setup (quick and plain)

  • MacBook Air M2
  • Node 18
  • Vite + React
  • Tailwind CSS v3.4
  • VS Code with Tailwind IntelliSense

If you ever need a quick way to prototype responsive menus outside of Tailwind, take a look at CSS Menu Tools—it’s a surprisingly handy companion.

I had a small dashboard. Charts, cards, tables. Nothing huge, but picky design. I needed odd spacing, new colors, and one weird grid.
Those same custom-value hacks came in handy the week I tinkered with Squarespace’s design panel—spoiler: you can inject far more CSS than the UI suggests, as I show over here.

The moment it broke

I added “p-13” for 13px padding. Nothing happened. Then I added “w-15%”. Still nothing. I forgot: Tailwind only builds what it sees. And it does not guess odd values.

So I switched to the “custom value” style. Like this:

  • p-[13px]
  • w-[15%]
  • top-[3.25rem]
  • grid-cols-[200px_1fr]

Boom. Tailwind rebuilt, and the styles appeared. It felt like magic, but it was just JIT doing its job.

When I really needed a rebuild

Sometimes the dev server didn’t catch a new file. Or I added classes in a string from an API. Those don’t show in the scan. So I had to rebuild and also make Tailwind “know” what to keep.

Here’s my tailwind.config.js that got me over the hump:

// tailwind.config.js
module.exports = {
  content: [
    "./index.html",
    "./src/**/*.{js,ts,jsx,tsx}",
    "./components/**/*.{js,ts,jsx,tsx}",
  ],
  theme: {
    extend: {
      colors: {
        brand: {
          DEFAULT: "#0ea5e9",
          dark: "#0369a1",
          light: "#7dd3fc",
        },
      },
      spacing: {
        13: "3.25rem", // tailwind doesn’t ship this one by default
      },
    },
  },
  plugins: [
    require("@tailwindcss/forms"),
    require("@tailwindcss/typography"),
  ],
  safelist: [
    "bg-brand",
    "bg-brand-dark",
    "text-brand",
    { pattern: /(bg|text|border)-(red|blue|green)-(100|500|700)/ },
  ],
};

Why the safelist? I had some styles coming from data. Like a status color. If Tailwind can’t see the class in the code, it won’t build it. Safelist tells it, “keep these anyway.” If you’re curious about how this evolves in v4, there’s a detailed answer on Stack Overflow.

Real classes I added (and used)

  • Buttons
    • "px-3 py-2 font-medium text-white bg-emerald-600 hover:bg-emerald-700 active:bg-emerald-800 focus:outline-none focus:ring-2 focus:ring-emerald-400"
  • Odd spacing
    • "p-[13px] mt-[7px] gap-[3px]"
  • Semi see-through hover
    • "hover:bg-lime-600/80"
  • Custom grid
    • "grid grid-cols-[200px_1fr] md:grid-cols-[260px_1fr]"
  • Fancy width
    • "w-[15%] md:w-[22%]"
  • Aspect ratio for images
    • "aspect-[4/3] object-cover"
  • A CSS variable color (handy in themes)
    • "bg-[–brand] text-white"

I also tossed some shared styles into a small component layer. It kept my JSX sane:

/* src/styles/tailwind.css */
@tailwind base;
@tailwind components;
@tailwind utilities;

@layer components {
  .btn-primary {
    @apply inline-flex items-center gap-2 px-3 py-2 rounded-md
    font-medium text-white bg-brand hover:bg-brand-dark
    focus:outline-none focus:ring-2 focus:ring-brand;
  }

  .card {
    @apply rounded-lg border border-gray-200 bg-white p-4 shadow-sm;
  }
}

Now I can just write:

  • className="btn-primary"
  • className="card"

Cleaner. Faster. Less noise.

The commands that actually helped

  • Dev with fast rebuilds:
    • "npm run dev" with Vite was enough. Each save rebuilt in under a second for me.
  • Full build:
    • "npm run build" gave me a tiny CSS file. Mine was about 64 KB gzipped.

When the rebuild didn’t catch something, I stopped and restarted the dev server. Old school trick. Still works.

Things that bit me (so you don’t get bit)

  • Missing content paths. I forgot to add “./components” at first. Tailwind didn’t see the classes inside there. No build, no styles. Easy fix. (See the official content configuration docs for how the scanner works.)
  • Classes made from variables. Like "bg-${color}". Tailwind can’t read that. I had to use safelist. Or switch to CSS variables.
  • Extra slow on a big repo. On my old laptop, file watch made the fan spin. On the Air, it was fine. If it drags, trim your content globs.
  • IntelliSense lag. The VS Code plugin didn’t show my new colors until I saved tailwind.config.js. Save it again if it acts weird.

A tiny performance note

Dev CSS was huge, like a few megabytes. That’s normal. After "npm run build", it shrank a lot. My page felt snappy. No flash between saves on Vite. Only a small blink when I changed big layouts. Pretty smooth.
Stripping out unused framework CSS can shave off even more; I did something similar in WordPress by axing Gutenberg’s bundle and documented the gains in this write-up.

If you’re curious how a production-scale adult social network keeps its pages lightweight yet feature-rich using similar utility-first tactics, swing by Fuckbook—exploring their live UI can give you practical inspiration for balancing performance with interaction-heavy components.
Likewise, if you want to see how a city-specific escort directory leans on clean utility classes to present dozens of profile cards without bogging down load times, check out Slixa Pasadena—the listing page is a great real-world example of responsive grids, filter panels, and subtle hover interactions that you can study and adapt for your own builds.

A small digression: making charts match

I use Chart.js. I wanted chart colors to match Tailwind. I used the same hex codes from theme.extend. I kept them in a tiny "theme.ts" file. Less guessing. More trust.

When you should rebuild

  • You add new files or folders with classes.
  • You use odd values (like p-[13px]) and Tailwind didn’t pick them up.
  • You moved classes into strings or data.
  • You added plugins (forms, typography, or something like daisyUI).

If you do that and still see nothing, restart dev. Then check content paths again. Nine times out of ten, it’s that.

My verdict

I was stuck. Rebuilding Tailwind and extending the config set me free. I got the odd sizes, the fancy grid, and clean buttons. The work took an hour. The payoff lasts.

Would I do it again? Yep. It felt like getting a fresh set of crayons when the old ones were down to nubs.

Quick cheat sheet

  • Use custom values: p-[13px], w-[15%], aspect-[4/3]
  • Extend theme for repeat stuff: colors, spacing
  • Safelist classes you build from data
  • Keep content paths tight and correct
  • Add a components layer with @apply for shared styles
  • Restart dev if it acts grumpy

And if you ever have to squeeze custom snippets into a hosted editor like Website.com, I recorded what sticks and what doesn’t right here.

If you’re stuck like I was—just rebuild Tailwind, teach it your shapes and colors, and keep going. It’s not fancy. It just

Laravel 11 + My Own CSS: What I Did, What I Loved, What Bugged Me

Hi, I’m Kayla. I built a small client dashboard with Laravel 11 last month. It needed clean buttons, a simple card look, and a calm blue theme. I wanted full control, so I wrote my own CSS. Was it smooth? Mostly. And when it wasn’t, I scribbled notes and fixed it. Coffee helped.

What I started with

Fresh Laravel 11. Vite handles the assets. Nothing fancy.
If you ever want to peek under the hood, the Laravel’s official documentation on asset bundling with Vite walks through every knob and switch.

  • I ran: composer create-project laravel/laravel example-app
  • Then: npm install and npm run dev
  • I used the default layout and added my styles with Vite

You know what? The hot reload felt great. Save, switch tabs, done.

If you want the blow-by-blow setup, I jotted a separate log of the process in this detailed Laravel 11 + custom CSS diary.

How I wired my CSS

I tried three ways. All worked. I’ll show you what stuck for me.

If you just need a quick, lightweight navigation bar to drop into any of these approaches, grab one of the pure-CSS snippets from CSS Menu Tools and paste it in—you’ll be tweaking colors in seconds.

1) Put styles in the default app.css

File: resources/css/app.css

/* Theme */
:root {
  --brand: #2563eb; /* bright blue */
  --brand-dark: #1e40af;
  --ink: #0f172a;   /* deep slate */
  --paper: #ffffff;
}

/* Base */
html, body {
  background: var(--paper);
  color: var(--ink);
  font-family: ui-sans-serif, system-ui, -apple-system, "Segoe UI", Roboto, Arial, sans-serif;
  line-height: 1.5;
}

/* Buttons */
.btn {
  display: inline-flex;
  gap: .5rem;
  align-items: center;
  padding: .6rem 1rem;
  border-radius: .5rem;
  border: 1px solid transparent;
  cursor: pointer;
  transition: background .15s ease, transform .05s ease;
}

.btn-primary {
  background: var(--brand);
  color: #fff;
}

.btn-primary:hover {
  background: var(--brand-dark);
  transform: translateY(-1px);
}

/* Cards */
.card {
  background: #fff;
  border: 1px solid #e5e7eb;
  border-radius: .75rem;
  box-shadow: 0 2px 6px rgba(15, 23, 42, .05);
  padding: 1rem;
}

/* Simple grid */
.grid {
  display: grid;
  gap: 1rem;
  grid-template-columns: 1fr;
}

@media (min-width: 768px) {
  .grid-2 { grid-template-columns: 1fr 1fr; }
}

Then I made sure Blade pulled it in.

File: resources/views/layouts/app.blade.php

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="utf-8">
  <title>{{ $title ?? 'Dashboard' }}</title>
  @vite(['resources/css/app.css', 'resources/js/app.js'])
  @stack('styles') {{-- for page-only styles --}}
</head>
<body class="antialiased">
  <main class="container">
    {{ $slot ?? '' }}
    @yield('content')
  </main>
</body>
</html>

That’s it. Vite served it. My buttons showed up blue. I smiled.

2) Split out a custom.css and import it

I wanted smaller files. So I made a second file.

File: resources/css/custom.css

/* Login page tweaks */
.login-box {
  max-width: 420px;
  margin: 6rem auto;
}

.help-text {
  font-size: .85rem;
  color: #64748b;
}

Then I linked it from app.css.

File: resources/css/app.css

@import './custom.css';

/* rest of app.css stays the same */

This kept my general theme in app.css and page bits in custom.css. Nice and tidy.

3) Page-only CSS with Blade stacks

For one-off polish, I used a stack. No new file. Quick and a little sneaky.

In the layout head I had:

@stack('styles')

On my stats page:

@push('styles')
<style>
.badge {
  display: inline-block;
  background: #fef3c7;
  color: #92400e;
  border: 1px solid #f59e0b;
  padding: .2rem .5rem;
  border-radius: .375rem;
}
</style>
@endpush

I wouldn’t do this for big chunks. But for one badge? Perfect.

Real examples from my build

I made a sales card with a little hover. It felt lively but not loud.

Blade:

<div class="card">
  <h2 class="mb-2">Monthly Sales</h2>
  <p class="text-muted">$42,310</p>
  <button class="btn btn-primary">Export CSV</button>
</div>

CSS (in app.css):

.card:hover {
  box-shadow: 0 8px 18px rgba(15, 23, 42, .08);
}
.text-muted { color: #6b7280; }
.mb-2 { margin-bottom: .5rem; }

I also added a tiny dark mode, because late-night fixes are real.

@media (prefers-color-scheme: dark) {
  :root {
    --paper: #0b1220;
    --ink: #e5e7eb;
  }
  .card {
    background: #0f172a;
    border-color: #1f2937;
    box-shadow: none;
  }
  .btn-primary {
    background: #1e3a8a;
  }
}

If you use Tailwind with Laravel 11

I did on a second page. The Tailwind CSS official guide for installing Tailwind with Laravel lays out the exact install and configuration steps. Tailwind’s base styles can override your stuff. The fix for me was order. I kept my custom CSS after Tailwind imports. In app.css:

@tailwind base;
@tailwind components;
@tailwind utilities;

/* My overrides last */
.btn-primary { background: var(--brand); }

If something still lost, I used a class with higher weight, not !important. Names like .btn.btn-primary beat a single class most times.
I even went down the rabbit hole of recreating Tailwind’s utility system myself—here’s how that experiment unfolded.

While working on another Laravel side-project, I had to theme a privacy-minded chat component for mobile users. To spark ideas, I looked at how mainstream discreet-messaging tools polish their UI—everything from bubble gradients to “clear chat” warnings. The most concise roundup I found was this guide to modern sexting messengers: top sexting apps—scrolling through it gives instant inspiration on layout conventions, safety prompts, and monetization hooks you might want to borrow for any chat or DM feature.

If your project also needs to present location-based premium services or profile listings, it helps to study how directories lay out cards, filters, and calls-to-action. I grabbed a few visual cues from Slixa Boulder’s escort listing—the way they surface key info above the fold and keep the card grid responsive is a practical model you can adapt for any marketplace UI.

The admin-only stylesheet trick

I had a heavier table look for admins. I loaded a second CSS file only on admin pages.

In resources/views/layouts/admin.blade.php:

@vite(['resources/css/app.css', 'resources/css/admin.css', 'resources/js/app.js'])

And the file:

resources/css/admin.css

.table {
  width: 100%;
  border-collapse: collapse;
}

.table th, .table td {
  padding: .75rem;
  border-bottom: 1px solid #e5e7eb;
}

.table tr:hover {
  background: #f9fafb;
}

Fast and clear. Users never saw it on public pages.

Little snags I hit (and fixed)

  • CSS didn’t change? I forgot npm run dev. I ran it, and it worked.
  • Wrong import path. I wrote @import 'custom.css' instead of ./custom.css. Fixed the dot, fixed the day.
  • Tailwind fights. I moved my overrides to the bottom. That did it.
  • Cache made me grumpy. A hard refresh helped

I Removed Link Underlines With CSS. Here’s What Actually Worked.

I’m Kayla, and yes, I’ve done the “make all links look clean” thing. More than once. I tried it on a client’s fashion blog, my own portfolio, and a SaaS dashboard. Some parts sang. Some bits… didn’t. You know what? Removing link underlines can look neat. But it can also hurt people who need clear cues.

So I’ll show what I did, what broke, what I kept, and the exact CSS that stuck.


Quick take

  • Good for nav bars, buttons, and cards.
  • Risky inside long paragraphs.
  • Keep strong focus and hover states.
  • Test on phones. It’s different with thumbs.

I tested on: Chrome 128 (Windows 11 + macOS), Safari 17 (macOS Sonoma + iOS 17), and Firefox 130 (macOS). Real devices: MacBook Air M2, a beat-up Windows laptop, and an iPhone 15. Nothing fancy. Just real screens.


Why I even removed underlines

Short story. A client said, “Links feel noisy.” The nav looked busy. Card grids looked cramped. I agreed. But removing all underlines? That felt wrong in long text. Reading a blog post with zero underlines is like walking without street signs.

So I split it: remove underlines in UI parts. Keep them in content. For a quick primer on the simplest CSS you can use for that, the folks at HubSpot outline a tidy snippet that mirrors what I started with.


Real example 1: Clean nav, but still clear

This was for a fashion blog header. Simple, neat, still clickable.

HTML:

<nav class="site-nav">
  <a href="/">Home</a>
  <a href="/new">New</a>
  <a href="/sale">Sale</a>
  <a href="/contact">Contact</a>
</nav>

CSS:

.site-nav a {
  text-decoration: none;
  color: #111;
  padding: 0.5rem 0.75rem;
  display: inline-block; /* bigger tap target */
}

.site-nav a:hover,
.site-nav a:focus-visible {
  text-decoration: underline;
}

.site-nav a:focus-visible {
  outline: 2px solid currentColor;
  outline-offset: 2px;
}

Why it worked: no underline by default, but a clear underline on hover and on keyboard focus. I like the outline too. It helps folks who tab through links. It helped me, honestly. If you want a quick way to experiment with nav styles, I sometimes spin up a demo in CSS Menu Tools, then pull the bits I need.

If you’d like to see the full blow-by-blow from my very first test run, I logged it in a companion case study: I removed link underlines with CSS. Here’s what actually worked.


Real example 2: In articles, I kept the underline (but made it nicer)

My portfolio posts needed clear links. So I didn’t remove them. I just styled them so they looked sharp.

article a,
.prose a {
  text-decoration: underline;
  text-underline-offset: 0.15em;
  text-decoration-thickness: 0.08em;
  text-decoration-skip-ink: auto;
}

article a:hover,
.prose a:hover {
  text-decoration-thickness: 0.12em;
}

article a:visited,
.prose a:visited {
  color: #6b3fa0; /* legal visited change */
}

This felt friendly. The underline sits a bit lower. Ink skips the descenders on letters like g and y. It reads clean.


For a pricing page, I had links that behaved like buttons. Underlines looked odd there.

HTML:

<a class="btn-link" href="/pricing">See pricing</a>

CSS:

.btn-link {
  text-decoration: none;
  color: #0b6bcb;
  font-weight: 600;
  border-bottom: 2px solid currentColor; /* visual anchor */
  padding-bottom: 2px;
}

.btn-link:hover,
.btn-link:focus-visible {
  border-bottom-color: transparent;
  outline: 2px solid currentColor;
  outline-offset: 2px;
}

It reads “button” without faking a real button. And it’s still keyboard-friendly.

If you want to peek at how a real-world product leans on bold, underline-free buttons to drive sign-ups, the team behind Plancul.app keeps the call-to-action crisp and clear; browsing their homepage is a quick way to see these principles in the wild.

While auditing directories that juggle dozens of thumbnail cards, I also pulled up the Michigan listings on Slixa to see how they strip default underlines yet maintain obvious card interactivity; it’s a handy benchmark when you need proof that card-level links can stay intuitive even in a dense grid.


I had product cards. Underlines inside a tight grid looked messy. So I stripped them and made the whole card clickable.

HTML:

<a class="card" href="/product/123">
  <img src="dress.jpg" alt="Red summer dress">
  <h3>Summer Dress</h3>
  <p>Light and breezy.</p>
</a>

CSS:

.card {
  text-decoration: none;
  color: inherit;
  display: block;
  padding: 1rem;
  border: 1px solid #e5e7eb;
  border-radius: 8px;
}

.card:hover,
.card:focus-visible {
  box-shadow: 0 0 0 3px #cde4ff;
}

.card h3 {
  text-decoration: none; /* prevent nested underline defaults */
}

It looked tidy. And with a strong focus ring, I didn’t lose clarity.


What went wrong (and how I fixed it)

  • I once set a { text-decoration: none; } globally. Big mistake. Blog posts lost their cues. People missed links. I rolled it back and scoped it to nav, cards, and buttons only. I’m not alone—Stack Overflow’s highest-voted answer on the topic flags the same pitfall.
  • In Safari, focus rings looked thin on dark headers. I bumped outline to 3px on dark themes.
  • On mobile, hover doesn’t exist. So I kept a bold color or a border cue that shows on focus as well.
  • A client used Tailwind. Their reset made some underlines vanish. I added utilities: underline for prose, no-underline for nav.

On a few WordPress builds, Gutenberg’s default CSS was the next hurdle. I ended up stripping most of it and wrote about the fallout here: I removed Gutenberg CSS in WordPress—was it worth it?

For component libraries like PrimeVue, the cascade can get just as unruly. I shared the exact selectors I overrode in this de-stress recap: How I override CSS in PrimeVue and kept my sanity

Tailwind quick helpers I used:

  • prose links: underline underline-offset-2
  • nav: no-underline hover:underline focus-visible:underline
  • focus: focus-visible:outline focus-visible:outline-2 focus-visible:outline-current

Bootstrap note:

  • .text-decoration-none removes underlines. I paired it with .link-underline on hover via custom CSS.

My small, reliable CSS set

I carry this between projects. It keeps me out of trouble.

/* 1) Keep underlines in content */
.prose a,
article a {
  text-decoration: underline;
  text-underline-offset: 0.15em;
  text-decoration-thickness: 0.08em;
  text-decoration-skip-ink: auto;
}

/* 2) Remove underlines in UI zones */
.site-nav a,
.card a,
.btn-link,
.footer-nav a {
  text-decoration: none;
}

/* 3) Strong focus for everyone */
a:focus-visible {
  outline: 2px solid currentColor;
  outline-offset: 2px;
}

/* 4) Hover or focus turns on a cue if underline is off */
.site-nav a:hover,
.site-nav a:focus-visible,
.footer-nav a:hover,
.footer-nav a:focus-visible {
  text-decoration: underline;
}

/* 5) Tap targets feel nicer */
.site-nav a,
.footer-nav a {
  display: inline-block;
  padding: 0.5rem 0.75rem;
}

/* 6) Visited links stay legal and readable */
.prose a:visited {
  color: #6b3fa0;
}

Accessibility check I actually run

  • Can I tab through all links? Do I see a clear ring?