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

推荐订阅源

C
CXSECURITY Database RSS Feed - CXSecurity.com
Security Latest
Security Latest
V
Vulnerabilities – Threatpost
Exploit-DB.com RSS Feed
Exploit-DB.com RSS Feed
L
LINUX DO - 最新话题
N
News and Events Feed by Topic
P
Proofpoint News Feed
G
GRAHAM CLULEY
NISL@THU
NISL@THU
S
Securelist
Recent Commits to openclaw:main
Recent Commits to openclaw:main
Schneier on Security
Schneier on Security
www.infosecurity-magazine.com
www.infosecurity-magazine.com
Application and Cybersecurity Blog
Application and Cybersecurity Blog
T
Threat Research - Cisco Blogs
Threat Intelligence Blog | Flashpoint
Threat Intelligence Blog | Flashpoint
T
Tenable Blog
Google DeepMind News
Google DeepMind News
Hacker News - Newest:
Hacker News - Newest: "LLM"
Help Net Security
Help Net Security
C
CERT Recently Published Vulnerability Notes
T
The Exploit Database - CXSecurity.com
I
Intezer
阮一峰的网络日志
阮一峰的网络日志
AI
AI
PCI Perspectives
PCI Perspectives
Hacker News: Ask HN
Hacker News: Ask HN
aimingoo的专栏
aimingoo的专栏
宝玉的分享
宝玉的分享
博客园 - 【当耐特】
腾讯CDC
The Cloudflare Blog
Spread Privacy
Spread Privacy
Latest news
Latest news
有赞技术团队
有赞技术团队
D
Docker
Cyberwarzone
Cyberwarzone
L
LINUX DO - 热门话题
S
Secure Thoughts
Hugging Face - Blog
Hugging Face - Blog
K
Kaspersky official blog
M
MIT News - Artificial intelligence
N
News | PayPal Newsroom
H
Hackread – Cybersecurity News, Data Breaches, AI and More
S
SegmentFault 最新的问题
J
Java Code Geeks
S
Security Affairs
The Register - Security
The Register - Security
云风的 BLOG
云风的 BLOG
Cyber Security Advisories - MS-ISAC
Cyber Security Advisories - MS-ISAC

Tailwind CSS Blog

Tailwind CSS v4.3: Scrollbars, new colors, and more Vanilla JavaScript support for Tailwind Plus Vanilla JavaScript support for Tailwind Plus Tailwind CSS v4.1: Text shadows, masks, and tons more Tailwind UI is now Tailwind Plus Tailwind UI is now Tailwind Plus Tailwind CSS v4.0 Tailwind CSS v4.0 Tailwind CSS v4.0 Beta 1 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 Automatically clean up whitespace and duplicate class names Catalyst: Application layouts, navigation menus, description lists, and more Headless UI v2.0 for React Headless UI v2.0 for React We're hiring a Design Engineer + Staff Engineer We're hiring a Design Engineer + Staff Engineer Open-sourcing our progress on Tailwind CSS v4.0 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 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 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 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.6, Tailwind UI team management, Tailwind Play improvements, and more Headless UI v1.5: The One With Comboboxes Automatic Class Sorting with Prettier Automatic Class Sorting with Prettier Effortless Typography, Even in Dark Mode Effortless Typography, Even in Dark Mode Standalone CLI: Use Tailwind CSS without Node.js Tailwind CSS v3.0 Tailwind CSS v3.0 Introducing Tailwind UI Ecommerce Introducing Tailwind UI Ecommerce Headless UI v1.4: The One With Tabs Tailwind CSS v2.2 Tailwind CSS v2.2 Tailwind UI: Now with React + Vue support Headless UI v1.0 Headless UI v1.0 Tailwind CSS v2.1 Tailwind CSS v2.1 Heroicons v1.0 Heroicons v1.0 Just-In-Time: The Next Generation of Tailwind CSS Welcoming James McDonald to Tailwind Labs Welcoming James McDonald to Tailwind Labs "Tailwind CSS: From Zero to Production" on YouTube Welcoming David Luhr to Tailwind Labs Welcoming David Luhr to Tailwind Labs Multi-line truncation with @tailwindcss/line-clamp Multi-line truncation with @tailwindcss/line-clamp Tailwind CSS v2.0 Tailwind CSS v2.0 Tailwind CSS v1.9.0 Tailwind CSS v1.9.0 Introducing Tailwind Play Introducing Tailwind Play Headless UI: Unstyled, Accessible UI Components "What's new in Tailwind CSS?" on YouTube "What's new in Tailwind CSS?" on YouTube Tailwind CSS v1.8.0 Tailwind CSS v1.8.0 Utility-Friendly Transitions with @tailwindui/react Utility-Friendly Transitions with @tailwindui/react Introducing Heroicons.com Introducing Heroicons.com Tailwind CSS v1.7.0 Tailwind CSS v1.7.0 From Nine Hundred to One: How We Hired Robin Malfait Tailwind CSS v1.6.0 Tailwind CSS v1.6.0 Simon Vrachliotis Joins Tailwind Labs Simon Vrachliotis Joins Tailwind Labs Welcoming Brad Cornes to the Team Welcoming Brad Cornes to the Team Tailwind CSS v1.5.0 Tailwind CSS v1.5.0 Introducing Tailwind CSS Typography Introducing Tailwind CSS Typography Building the Tailwind Blog with Next.js Building the Tailwind Blog with Next.js Introducing linting for Tailwind CSS IntelliSense 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!