GitShow/tailwindlabs/tailwindcss
tailwindlabs

tailwindcss

A utility-first CSS framework for rapid UI development.

by tailwindlabs
csscss-frameworkfunctional-csspostcssresponsivetailwindcssutility-classes
Star on GitHubForkWebsitenpm

TypeScript

97.2k stars5.6k forks370 contributorsActive · 2h agoSince 2017v4.3.3MIT

Meet the team

See all 370 on GitHub →
adamwathan
adamwathan2.9k contributions
RobinMalfait
RobinMalfait1.0k contributions
depfu[bot]Bot
depfu[bot]614 contributions
thecrypticace
thecrypticace444 contributions
dependabot-preview[bot]Bot
dependabot-preview[bot]350 contributions
reinink
reinink342 contributions
philipp-spiess
philipp-spiess295 contributions
bradlc
bradlc55 contributions

Languages

View on GitHub →
TypeScript79.9%
Rust17.9%
JavaScript0.7%
CSS0.6%
HTML0.6%
Haml0.4%

Commit activity

Last 12 weeks · 95 commits

Full graph →

Community health

4 of 6 standards met

Community profile →
62
✓README✓License✓Contributing○Code of Conduct○Issue Template✓PR Template

Recent PRs & issues

Active · Last activity 2h ago
See all on GitHub →
DanhezCode
Broken HMR with preact, automatic full page reload periodically, similar to #19903OpenIssue

What version of Tailwind CSS are you using? v4.3.3 What build tool (or framework if it abstracts the build tool) are you using? preact@11.0.0-rc.0 or preact@10.29.8, vite@8.2.1 and tailwindcss@4.3.3, @tailwindcss/vite@4.3.3 What version of Node.js are you using? bun@1.3.14 What browser are you using? Edge What operating system are you using? Ubuntu Reproduction URL Describe your issue** The error is very similar to #19903, causing a full page reload and loss of all state periodically, even without any interaction. It's closely related to , and the behavior disappears if I disable on the . I also tried and and encountered the same problem.

DanhezCode · 11m ago
zackradisic
Bun pluginOpenPR

(Sorry for creating this PR without opening an issue first) This PR implements a Bun plugin that makes TailwindCSS fast in Bun. (bundling 2048 html + react + tailwind files) Overview This plugins is comprised of two parts: A regular Bun bundler plugin which is the main driver of everything and invokes the native bundler plugin A native bundler plugin which parallelizes the module graph scanning of candidates. Tailwind was part of the motivation for implementing this API. Native bundler plugin The native bundler plugin is used to scan the module graph in parallel with the struct from . The main logic for this code is in the function. Native bundler plugins run in parallel on Bun's bundler threads and do not need to do UTF-16 UTF-8 string conversions. This speeds up the plugin a lot. Native bundler plugins are NAPI modules which export additional symbols (since NAPI modules themselves are dynamically loaded libraries which can be 'd). The crate handles the boilerplate for creating one. I placed the Bun plugin inside the existing (the package). This reduces the need to create more compiled artifacts at the cost of a relatively small binary size change: Please let me know if you would like me to split it out into its own separate package if you don't like the binary size change. Sharing state between the native plugin and JS The scanned candidates and other state are held inside a NAPI External. The struct in the code that does this is called . A NAPI External is a NAPI value which can be given to JS and which holds a data pointer. This data is inaccessible to JS, but a NAPI module can dereference the data and convert it to NAPI values. This looks a bit like this on the Rust side: And the JS side: version bump The crate was updated to version so we can use the function to turn an 's pointer back into . JS plugin The JS plugin uses logic copied over from the vite plugin implementation but modified to work with Bun's plugin API. It invokes the native bundler plugin using the plugin API function: One thing to note is that Bun's bundler currently does not have an API that is analogous to , so there is currently no way to add additional files to the module graph. Testing I added a file, please let me know if you would like more tests

zackradisic · 8h ago
benjamincanac
Don't scan sibling files of a concrete `@source` inside an auto source rootOpenPR

Summary A concrete file that sits inside an auto detection root scans the file's entire parent directory: With the project root as an auto source, every sibling of is scanned and their classes end up in the output. The same directive works correctly when it points outside the root (since #20263). This is the remaining half of #20255. skips the + restriction when the pattern's base is inside an unrestricted root, because everything under that root is walked anyway. But that's not true when the base hides behind a directory the auto walk prunes, like or a git-ignored folder. In that case the pattern's own walk root is the only thing reaching the file, and its ignore rules are just: so all the siblings are walked and included too. To fix this, an auto root only counts as covering a pattern base when its walk actually reaches it: the path down to the base doesn't cross a default-ignored directory and the base isn't git-ignored. The git-ignored check reuses the ancestor walk (and cache) that already promotes auto sources to external sources. External roots and patterns still cover everything under them, and patterns in ordinary subdirectories behave like before, restricting those would hide siblings the auto source should pick up. The walk now follows git's precedence: the nearest with a definitive answer wins, so a directory re-included by a deeper pattern is not treated as ignored. Because that walk is shared, re-included directory sources also stay auto sources instead of being promoted to external ones. For context, I ran into this in Nuxt UI: we emit per-component lines into , and the narrowed list produced byte-identical CSS to sourcing the whole directory (nuxt/ui#6731). Test plan Three new integration tests: concrete file sources behind and behind a git-ignored directory (both failed before with the sibling's candidates included), and a re-included directory where the siblings must stay. Three new unit tests for , including a control for patterns in ordinary covered subdirectories. passes, clean, no new clippy warnings. Verified end to end with on Vite 8 by patching the built oxide binary into a reproduction project: a file inside the root now only ships that file's classes; whole-directory sources and auto detection are unchanged. 🤖 Generated with Claude Code

benjamincanac · 20h ago

Recent fixes

View closed PRs →
skirchner2323-kinetic
Scanned candidate emitted with corrupted bytes (`child` → `U+FFFD \x06 U+FFFD \x01`) by a long-lived `next dev` (Turbopack) process — evidence against the scanner's `from_utf8_unchecked` safety assumptionClosedIssue

Summary A long-running (Turbopack) process in a pnpm monorepo entered a state where Tailwind's generated CSS contained a corrupted copy of one arbitrary-variant candidate. The bytes of in the candidate (present verbatim in a source file) were replaced by the four characters , producing unparseable CSS. Every route then failed with lightningcss's , and the state persisted in memory until the dev server was restarted. A production of the identical tree compiled cleanly every time, before, during, and after. We do not have a reproduction recipe — this is a forensic report of a corrupted state captured live. We're filing it because the corruption is demonstrably in the candidate string itself, before variant expansion (see Analysis), which bears directly on the safety assumption that led to closing #19410 ( in the scanner is fine because "the extractor's implementation should guarantee that the resulting candidates are already UTF-8"). The characters indicate a lossy UTF-8 conversion happened somewhere downstream of bytes that were not valid UTF-8. Environment tailwindcss / @tailwindcss/postcss: 4.3.3 () next: 16.2.12, dev server (Turbopack), via the PostCSS plugin ( → ) node: v26.5.0 (nvm), pnpm 11, pnpm workspace monorepo (app at ) macOS 26.5.2, Apple Silicon (arm64) Dev server had been running for a long stretch (hours+) and had served many on-demand route compiles; the machine was under heavy load at times (parallel Playwright suites against sibling dev servers, several processes in worktrees of the same repo). The source candidate : The error (verbatim, from the dev-overlay payload) Every route on the affected server returned HTTP 500 with this compilation error (control characters rendered here as `�\6 \1 childU+FFFD U+0006 U+FFFD U+0001[&>:last-child]:col-span-2.\[\&\>\\:last-child\]\:col-span-2> :last-child&childlast-��U+FFFDString::from_utf8_uncheckedcrates/oxide/src/scanner/mod.rsU+FFFD0x060x01 06 01.tsxglobals.css.next…:last-child…Scannerscan()next buildfrom_utf8` (or debug assertion) at that boundary would turn this silent state-corruption into a loud, attributable error.

skirchner2323-kinetic · 2h ago
mvanhorn
fix: Drop invalid UTF-8 scanner candidatesMergedPR

Summary Replace the three unchecked scanner conversions in with checked conversions that omit only extracted slices that are not valid UTF-8. Apply the check in the shared pipeline so initial scans, incremental calls, and CSS-variable extraction cannot insert invalid strings into scanner state, and apply the same policy to both branches of while preserving byte offsets and the legacy restoration. Keep the extractor's byte-oriented CSS identifier classification unchanged: accepting non-ASCII bytes during extraction is useful for valid multibyte code points, while the conversion boundary is the authoritative place to enforce the contract. The scanner currently converts extracted byte slices with unchecked UTF-8 constructors at the shared extraction boundary and both candidate-with-position branches. A source file containing a stray continuation byte can therefore produce an invalid , violating Rust's string invariant and allowing corrupted candidates to persist in a long-lived scanner. The thread provides a deterministic reproduction using invalid bytes inside an arbitrary value, so the problem no longer depends on reproducing the originally reported Turbopack race. Valid candidates found alongside malformed byte sequences must continue to be returned normally. Fixes #20368 Test plan Not applicable to this change. AI was used for assistance.

mvanhorn · 2h ago
RobinMalfait
Visualize scanner related testsMergedPR

This PR improves the scanner related tests a bit. Right now all the scanner tests (a lot of them) are somewhat hard to reason about and to figure out whether these are actually correct or not. With this PR, the existing are extended with a visualization of the file system tree, but with indicators to know whether or not a file was scanned or not. If a is present, it's content is also shown to make it easier to see why some files are included or not included. One of the outputs look like this: I'm sure we can cleanup a lot of these tests, simplify, deduplicate, but I didn't want to do that as part of this PR. This PR is purely adding this visualization. This uses the insta.rs library for (inline) snapshot tests. If at some point the snapshots change, then you get a nice UI: Test plan 1. All tests should pass [ci-all] 2. Nothing in the code itself changed, so nothing should break Stack created with GitHub Stacks CLI • Give Feedback 💬

RobinMalfait · 2h ago
Structured data for AI agents

Repository: tailwindlabs/tailwindcss. Description: A utility-first CSS framework for rapid UI development. Stars: 97229, Forks: 5582. Primary language: TypeScript. Languages: TypeScript (79.9%), Rust (17.9%), JavaScript (0.7%), CSS (0.6%), HTML (0.6%). License: MIT. Homepage: https://tailwindcss.com/ Topics: css, css-framework, functional-css, postcss, responsive, tailwindcss, utility-classes. Latest release: v4.3.3 (4w ago). Open PRs: 26, open issues: 27. Last activity: 2h ago. Community health: 62%. Top contributors: adamwathan, RobinMalfait, depfu[bot], thecrypticace, dependabot-preview[bot], reinink, philipp-spiess, bradlc, dependabot-support, MichaelDeBoey and others.

·@ofershap

Replace github.com with gitshow.dev