惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

Google Online Security Blog
Google Online Security Blog
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More
Stack Overflow Blog
Stack Overflow Blog
GbyAI
GbyAI
Microsoft Azure Blog
Microsoft Azure Blog
I
InfoQ
F
Fortinet All Blogs
N
Netflix TechBlog - Medium
Martin Fowler
Martin Fowler
腾讯CDC
C
CERT Recently Published Vulnerability Notes
博客园 - 聂微东
L
LINUX DO - 热门话题
Y
Y Combinator Blog
H
Hackread – Cybersecurity News, Data Breaches, AI and More
Threat Intelligence Blog | Flashpoint
Threat Intelligence Blog | Flashpoint
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
Microsoft Security Blog
Microsoft Security Blog
cs.CL updates on arXiv.org
cs.CL updates on arXiv.org
WordPress大学
WordPress大学
C
Cisco Blogs
A
Arctic Wolf
Latest news
Latest news
Jina AI
Jina AI
P
Proofpoint News Feed
博客园 - 叶小钗
Vercel News
Vercel News
T
Threat Research - Cisco Blogs
博客园 - 三生石上(FineUI控件)
K
Kaspersky official blog
C
Check Point Blog
H
Heimdal Security Blog
博客园 - Franky
小众软件
小众软件
The Register - Security
The Register - Security
Application and Cybersecurity Blog
Application and Cybersecurity Blog
Google DeepMind News
Google DeepMind News
AWS News Blog
AWS News Blog
The Hacker News
The Hacker News
T
The Exploit Database - CXSecurity.com
aimingoo的专栏
aimingoo的专栏
Project Zero
Project Zero
G
GRAHAM CLULEY
爱范儿
爱范儿
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
Scott Helme
Scott Helme
让小产品的独立变现更简单 - ezindie.com
让小产品的独立变现更简单 - ezindie.com
Exploit-DB.com RSS Feed
Exploit-DB.com RSS Feed
NISL@THU
NISL@THU

Tailwind CSS Blog

Tailwind CSS v4.3: Scrollbars, new colors, and more Vanilla JavaScript support for Tailwind Plus Tailwind CSS v4.1: Text shadows, masks, and tons more Tailwind UI is now Tailwind Plus Tailwind CSS v4.0 Tailwind CSS v4.0 Beta 1 Radiant: A beautiful new marketing site template Headless UI v2.1: Simplified transition API and improved multi-dialog support Automatically clean up whitespace and duplicate class names Catalyst: Application layouts, navigation menus, description lists, and more Headless UI v2.0 for React We're hiring a Design Engineer + Staff Engineer Open-sourcing our progress on Tailwind CSS v4.0 Introducing Catalyst: A modern UI kit for React Tailwind CSS v3.4: Dynamic viewport units, :has() support, balanced headlines, subgrid, and more Heroicons Micro: What are these, icons for ants? Meet Studio: Our beautiful new agency site template Tailwind Connect 2023: Recap of our first in-person event New changelog template + the biggest Tailwind UI update ever Tailwind CSS v3.3: Extended color palette, ESM/TS support, logical properties, and more Protocol: A beautiful starting point for your next API documentation site Tailwind CSS v3.2: Dynamic breakpoints, multi-config, and container queries, oh my! We built you a new personal website + Heroicons v2.0, Headless UI v1.7, and more New Tailwind CSS + Framer Motion template and Tailwind Jobs Tailwind UI: Site templates and all-access Tailwind CSS v3.1: You wanna get nuts? Come on, let's get nuts! Headless UI v1.6, Tailwind UI team management, Tailwind Play improvements, and more Headless UI v1.5: The One With Comboboxes Automatic Class Sorting with Prettier Effortless Typography, Even in Dark Mode Standalone CLI: Use Tailwind CSS without Node.js Tailwind CSS v3.0 Introducing Tailwind UI Ecommerce Headless UI v1.4: The One With Tabs Tailwind CSS v2.2 Tailwind UI: Now with React + Vue support Headless UI v1.0 Tailwind CSS v2.1 Heroicons v1.0 Just-In-Time: The Next Generation of Tailwind CSS Welcoming James McDonald to Tailwind Labs "Tailwind CSS: From Zero to Production" on YouTube Welcoming David Luhr to Tailwind Labs Multi-line truncation with @tailwindcss/line-clamp Tailwind CSS v2.0 Tailwind CSS v1.9.0 Introducing Tailwind Play Headless UI: Unstyled, Accessible UI Components "What's new in Tailwind CSS?" on YouTube Tailwind CSS v1.8.0 Utility-Friendly Transitions with @tailwindui/react Introducing Heroicons.com Tailwind CSS v1.7.0 From Nine Hundred to One: How We Hired Robin Malfait Tailwind CSS v1.6.0 Simon Vrachliotis Joins Tailwind Labs Welcoming Brad Cornes to the Team Tailwind CSS v1.5.0 Introducing Tailwind CSS Typography Building the Tailwind Blog with Next.js Introducing linting for Tailwind CSS IntelliSense
Compass: A starter kit for online courses
2025-05-15 · via Tailwind CSS Blog

I've been itching to get back into screencasting and teaching lately, so a couple of months ago I put together this free Build UIs that don't suck mini-course. People seemed to like it and now I want to do some bigger video projects, but there was a problem.

I am a software developer.

And as a software developer, much like I need to write my own static site generator before I can build my own personal website, I needed to build my own course platform before I could even think about putting together a video course.

Well fast-forward six weeks later and we just released Compass, a starter kit we designed with Tailwind CSS and Next.js for publishing your own online course.

Check out the live preview as always for the full experience.

We had a lot of fun working on this one, and got to play with a bunch of new tools and technologies and solve some interesting problems.


Picture-in-picture video

You might not have seen it before but most modern browsers have native Picture-in-Picture support. These APIs let you take a video and pop it out into a separate window that the user can move around and resize while still browsing the site.

We had this idea for Compass where if you started to play a course video and scrolled down the page, the video would move to the bottom right of the screen so you could still watch it while reading the page content.

We were hoping to use the Picture-in-Picture APIs for this, but it turns out you can't passively trigger them on scroll (for privacy/security reasons I guess?) — the user has to actually click something, similar to the clipboard APIs.

We ended up rolling our own simple thing instead, using IntersectionObserver, video events, and a bit of state to detect when the video was playing and offscreen, and added data attributes to the <video> element to so we could target them with utility classes:

<video  data-offscreen={isOffscreen ? "" : undefined}  data-playing={isPlaying ? "" : undefined}  className="data-offscreen:data-playing:fixed data-offscreen:data-playing:right-4 data-offscreen:data-playing:bottom-4"/>

I love using data attributes for this sort of thing, find the code reads a lot more like standard Tailwind stuff compared to a bunch of ternaries and conditional logic in JavaScript.


Parsing VTT files into transcripts

There's a section in Compass for interviews, which each include a video at the top of the page but also a pretty custom transcript UI below:

At first we weren't totally sure how we should approach this. Our first idea was to just write some React components for these pieces and throw the content directly into an MDX file, but it felt sort of unrealistic to expect anyone to ever author their transcripts in this totally custom format.

Then I had the idea to use a standard caption file format, like SRT. The problem was that for our needs, we needed to encode the current speaker (Tom or Annie in the screenshot above), and SRT has no standardized way of encoding that information in the file.

I did some more research and eventually landed on WebVTT, which is similar to SRT but does support speaker information, and is conveniently designed for the web.

WEBVTT00:00.000 --> 00:20.000<v Tom Harris>Hello fellow passengers, welcome to the Compass podcast. Today, we have a special guest, Annie King. She's the author of The Inevitable You: How to Embrace Your Path and Succeed with Relentless Precision. Annie, welcome to the show.00:20.000 --> 00:35.000<v Annie King>Thank you! I'm so happy to be here. And thanks for sending me the questions in advance — I'm really excited to share some of the ideas from the book with your viewers. I think we're going to have a lot of fun unpacking what it means to truly embrace your path.00:35.000 --> 00:45.000<v Tom Harris>Absolutely! I want to get into your book, but first I have to ask — what was it like growing up in a household that treated organization almost like...a sport?

So we wired things up to parse the transcript data from a .vtt file, and then map over that data to render it as a custom UI with React:

src/interview/[slug]/page.tsx

<div>  {transcript.map(({ start, speaker, text }) => (    <div key={start} className="col-span-2 grid grid-cols-subgrid items-baseline">      <TimestampButton start={start} videoId="video" className="justify-self-end" />      <div>        <p className="text-sm/7 font-semibold text-gray-950 dark:text-white">{speaker}</p>        {text.map((p, index) => (          <p key={index} className="mt-2 text-sm/7 whitespace-pre-wrap text-gray-700 dark:text-gray-400">            {p}          </p>        ))}      </div>    </div>  ))}</div>

Turned out pretty cool — I can imagine someone just generating a transcript in VTT format using AI, throwing it into the project and it'll automatically be rendered in a nice custom UI.


Extending Markdown images for dark mode and layout shift

The example content we came up with for Compass includes a lot of diagrams that we wanted to adapt between light and dark mode.

You can do this sort of thing a ton of different ways (the <picture> tag supports it natively for example), but we really wanted to keep the content files feeling as much like vanilla Markdown as possible.

So we came up with this idea of a {scheme} placeholder in the image URL that we replace with light or dark dynamically, loading the correct image based on the user's color scheme:

## The Myth of Free Will![Neurological Proof](/img/neuro-proof.{scheme}.png)Your brain makes decisions before you are even aware of them.

Now the underlying image component will automatically render neuro-proof.light.png or neuro-proof.dark.png depending on the current color scheme. And if you just want to use the same image in both, just don't include {scheme} in the URL at all.

We also wanted to avoid layout shift in the content, which you can do pretty easily these days by ensuring you give your images width and height attributes so the browser can compute the aspect ratio and reserve space for the image when it loads.

There's no standard way to express this in Markdown's image syntax, but after a bit of research we discovered some precedent in Obsidian.

Obsidian tacks the image dimensions on to the alt text, like this:

## The Myth of Free Will![Neurological Proof|2000x990](/img/neuro-proof.{scheme}.png)Your brain makes decisions before you are even aware of them.

So we used a custom MDX component to pull out the dimensions using the same format, and add those to the image to make sure there's no layout shift as the content loads.


So there you go — that's Compass! As always it's a free update for anyone with a Tailwind Plus license, so go and download the codebase, poke around, and have fun with it.

If you don't already have a Tailwind Plus license, think about getting one! Picking one up is the best way to support our work on Tailwind CSS and there's a ton of useful stuff in there.

Looking forward to using this template for some upcoming projects myself in the next couple of months!