// https://www.reddit.com/r/tailwindcss/comments/1icfwbo/here_are_10_tailwind_tricks_shared_by_shadcn_they/
// https://x.com/shadcn/status/1842329158879420864
// 1. Dynamic CSS Variables in Tailwind
<div style={{ "--width": isCollapsed ? "8rem" : "14rem" }} className="w-[--width] transition-all" />
// 2. Data Attribute State Management
<div
data-state={isOpen ? "open" : "closed"}
className="data-[state=open]:bg-blue-500"
/>
// 3. Nested SVG Controll
<div
data-collapsed={isCollapsed}
className="[&[data-collapsed=true]_svg]:rotate-180"
>
<svg>...</svg>
</div>
// 4. Parent-Child Style Inheritance
<section :data-collapsed="isCollapsed"
<div className="[[data-collapsed=true]_&]:rotate-180">
{/* Child inherits rotation when parent has data-collapsed=true */}
</div>
</section>
// 5. Group Data States
<div className="group" data-collapsed={isCollapsed}>
<div className="group-data-[collapsed=true]:rotate-180"/>
</div>
// 6. Data Slots
<div className="data-[slot=action]:*:hover:mr-0">
<div data-slot="action" class="-mr-10">...</div>
</div>
// 7. Peer Element Control
<button className="peer" :data-active="isActive">Menu</button>
<div className="peer-data-[active=true]:bg-blue-500"/>
// 8. Named Group Focus
<div className="group/menu">
<button className="group-focus-within/menu:bg-blue-500"/>
</div>
// 9. Group Has Selectors
<div className="group/menu">
<div className="group-has-[[data-active=true]]/menu:bg-blue-500"/>
</div>
// 10. Variant Props
<button
data-variant={variant}
className="data-[variant=ghost]:border-blue-500"
/>
<!-- https://play.tailwindcss.com/yyRSjWdDIv -->
<!--
https://tailwindcss.com/docs/adding-custom-styles#using-arbitrary-values
-->
<section class="m-5 *:mb-2 *:border *:text-red-400 [&_p]:text-blue-500">
<div>text1</div>
<div>text2</div>
<div>text3</div>
<div>text4</div>
<div>text5</div>
<p>Para 1</p>
<p>Para 2</p>
<div>text 6</div>
</section>
<div class="[&:nth-child(3)]:py-0">
<!-- ... -->
</div>
<ul role="list" class="space-y-4 [&>*]:rounded-lg [&>*]:bg-white [&>*]:p-4 [&>*]:shadow">
<li class="flex"> <!-- ... -->
</ul>
<ul
role="list"
class="space-y-4 [&>*]:rounded-lg [&>*]:bg-white [&>*]:p-4 [&>*]:shadow hover:[&>li:nth-child(2)>div>p:first-child]:text-indigo-500"
>
<ul class="m-5 [&>*:not(:last-child)]:text-green-500">
<li>1</li>
<li>2</li>
<li>3</li>
<li>4</li>
<li>5</li>
</ul
<ul class="m-5 [&>*:not(:last-child)]:after:content-[':)']">
<li>1</li>
<li>2</li>
<li>3</li>
<li>4</li>
<li>5</li>
</ul>
<div class="[--scroll-offset:56px] lg:[--scroll-offset:44px]">
<div class="[mask-type:luminance] hover:[mask-type:alpha]">
<div class="bg-[url('/what_a_rush.png')]">
When using arbitrary values, Tailwind can generally handle this ambiguity automatically based on the value you pass in:
<!-- Will generate a font-size utility -->
<div class="text-[22px]">...</div>
<!-- Will generate a color utility -->
<div class="text-[#bada55]">...</div>
Sometimes it really is ambiguous though, for example when using CSS variables:
<div class="text-[var(--my-var)]">...</div>
In these situations, you can “hint” the underlying type to Tailwind by adding a CSS data type before the value:
<!-- Will generate a font-size utility -->
<div class="text-[length:var(--my-var)]">...</div>
<!-- Will generate a color utility -->
<div class="text-[color:var(--my-var)]">...</div>
<!--
https://play.tailwindcss.com/sLrFGm1VtG
--
<!-- Via class, ale muze to chytnout i vyssi tridu, takze radsi jeste dat #ID na ten element a pres nej ve smyslu [#nejakeId.theme-light_&] -->
<section class="theme-light">
<article>
<div class="[.theme-light_&]:bg-red-200 [.theme-dark_&]:bg-gray-800">
Obsah
</div>
</article>
</section>
<!-- Přes data atribut -->
<div data-theme="dark" class="[&[data-theme='light']]:bg-red-200 [&[data-theme='dark']]:bg-gray-800">
Obsah
</div>
<!-- Nebo pro parent selector -->
<section data-theme="light">
<div class="[[data-theme='light']_&]:bg-red-200 [[data-theme='dark']_&]:bg-gray-800">
Obsah
</div>
</section>
<!--
:root {
--x: pink;
}
-->
<div class="hover:bg-[--x]"> kuku</div>
<!--
https://ishadeed.com/article/css-relative-colors/#adjust-the-opacity-with-color-mix
-->
<!-- works only for color from config not defined like css variables -->
<!--v2 -->
<div class="ring-msp-red-default/30"></div>
<!--v3 -->
<div class="ring-msp-red-default ring-opacity-30"></div>
<!-- Hack if color is defined like css variable in config -->
'my-red': 'var(--primary-color)', // '#ba0c2f',
<!--v2 hack -->
does not exist
<!--v3 hack -->
ring-[color-mix(in_srgb,theme(colors.my-red)_50%,transparent)]
<!--v4 -->
no hack needed, v4 is functional (read doc)
<!-- https://codepen.io/xqbuilds/pen/LYwvOer -->
<head>
<script src="https://cdn.tailwindcss.com"></script>
</head>
<body class="bg-black text-white flex items-center justify-center min-h-screen space-x-6">
<!-- Hover Dropdown -->
<div class="relative group">
<button class="bg-amber-900 hover:bg-amber-800 px-6 py-3 rounded-lg transition">
Hover Dropdown
</button>
<div class="absolute left-0 hidden w-40 bg-gray-800 rounded-lg group-hover:block">
<a href="#" class="block px-4 py-2 hover:bg-gray-700">Option 1</a>
<a href="#" class="block px-4 py-2 hover:bg-gray-700">Option 2</a>
<a href="#" class="block px-4 py-2 hover:bg-gray-700">Option 3</a>
<a href="#" class="block px-4 py-2 hover:bg-gray-700">Option 4</a>
</div>
</div>
<!-- Click Dropdown -->
<div class="relative">
<details>
<summary class="bg-teal-800 hover:bg-teal-700 px-6 py-3 rounded-lg cursor-pointer transition">
Click to Open
</summary>
<div class="absolute left-0 w-40 bg-gray-800 rounded-lg">
<a href="#" class="block px-4 py-2 hover:bg-gray-700">Option A</a>
<a href="#" class="block px-4 py-2 hover:bg-gray-700">Option B</a>
<a href="#" class="block px-4 py-2 hover:bg-gray-700">Option C</a>
<a href="#" class="block px-4 py-2 hover:bg-gray-700">Option D</a>
</div>
</details>
</div>
</body>
</html>
<html>
<head>
<meta charset="utf-8" />
<meta http-equiv="x-ua-compatible" content="ie=edge" />
<title>Sandbox - RJ</title>
<meta name="description" content="" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<script src="https://unpkg.com/@tailwindcss/browser@4"></script>
<script defer src="https://cdn.jsdelivr.net/npm/alpinejs@3.x.x/dist/cdn.min.js"></script>
</head>
<body>
<!-- Code here ... -->
</body>
</html>
/* Kevin Powell
https://codepen.io/kevinpowell/pen/ExrZrrw
(https://ryanmulligan.dev/blog/layout-breakouts/)
*/
.content-grid {
--padding-inline: 1rem;
--content-max-width: 900px;
--breakout-max-width: 1200px;
--breakout-size: calc(
(var(--breakout-max-width) - var(--content-max-width)) / 2
);
display: grid;
grid-template-columns:
[full-width-start] minmax(var(--padding-inline), 1fr)
[breakout-start] minmax(0, var(--breakout-size))
[content-start] min(
100% - (var(--padding-inline) * 2),
var(--content-max-width)
)
[content-end]
minmax(0, var(--breakout-size)) [breakout-end]
minmax(var(--padding-inline), 1fr) [full-width-end];
}
.content-grid > :not(.breakout, .full-width),
.full-width > :not(.breakout, .full-width) {
grid-column: content;
}
.content-grid > .breakout {
grid-column: breakout;
}
.content-grid > .full-width {
grid-column: full-width;
display: grid;
grid-template-columns: inherit;
}
img.full-width {
width: 100%;
max-height: 45vh;
object-fit: cover;
}
:root {
--color-scheme: dark;
--font-family: system-ui;
--fs-300: clamp(0.94rem, calc(0.92rem + 0.08vw), 0.98rem);
--fs-400: clamp(1.13rem, calc(1.06rem + 0.33vw), 1.31rem);
--fs-500: clamp(1.35rem, calc(1.21rem + 0.69vw), 1.75rem);
--fs-600: clamp(1.62rem, calc(1.37rem + 1.24vw), 2.33rem);
--fs-700: clamp(1.94rem, calc(1.54rem + 2.03vw), 3.11rem);
--fs-800: clamp(2.33rem, calc(1.7rem + 3.15vw), 4.14rem);
--fs-900: clamp(2.8rem, calc(1.85rem + 4.74vw), 5.52rem);
--clr-primary-300: hsl(219, 76%, 55%);
--clr-primary-400: hsl(219, 76%, 40%);
--clr-primary-500: hsl(219, 76%, 25%);
--clr-secondary-300: hsl(269, 75%, 55%);
--clr-secondary-400: hsl(269, 75%, 40%);
--clr-secondary-500: hsl(269, 75%, 25%);
--clr-accent-200: hsl(358, 85%, 80%);
--clr-accent-300: hsl(358, 72%, 65%);
--clr-accent-400: hsl(358, 72%, 50%);
--clr-accent-500: hsl(358, 72%, 35%);
}
*,
*::before,
*::after {
box-sizing: border-box;
}
html {
color-scheme: var(--color-scheme);
}
body {
margin: 0;
font-family: var(--font-family);
font-size: var(--fs-400);
line-height: 1.6;
}
h1,
h2,
h3,
h4,
h5,
h6,
p,
figure {
margin: 0;
}
img {
max-width: 100%;
display: block;
}
.site-title {
font-size: var(--fs-900);
line-height: 1.05;
text-transform: uppercase;
}
.section-title {
font-size: var(--fs-800);
line-height: 1.1;
}
.bg-primary {
background: var(--clr-primary-500);
}
.visually-hidden {
clip: rect(0 0 0 0);
clip-path: inset(50%);
height: 1px;
overflow: hidden;
position: absolute;
white-space: nowrap;
width: 1px;
}
.call-to-action {
padding: 1rem;
background: hsl(0 0% 100% / 0.15);
}
.wrapper {
width: calc(100% - 3rem);
max-width: 900px;
margin-inline: auto;
}
.flow > * + * {
margin-top: var(--flow-spacing, 1em);
}
.section-padding {
padding-block: 2.5rem;
}
.primary-header {
padding-block: 1rem;
margin-block-end: 3rem;
background: var(--clr-accent-200);
color: var(--clr-primary-500);
}
.primary-header__layout {
display: flex;
align-items: center;
justify-content: space-between;
}
.logo {
max-width: 250px;
}
nav ul {
list-style: none;
margin: 0;
padding: 0;
display: flex;
flex-wrap: wrap;
gap: max(5vw, 1rem);
}
nav a {
color: inherit;
text-decoration: none;
}
nav a:hover,
nav a:focus {
color: var(--clr-accent-500);
text-decoration: underline;
}
.even-columns {
display: flex;
gap: 1rem;
}
<!--
https://play.tailwindcss.com/B8YFBxQAJO
-->
<div class="group relative flex h-[10em] w-[10em] items-center justify-center rounded-[1.5em] px-[0.5rem] pt-[1rem]">
<svg class="absolute left-1/2 top-[calc(50%+8px)] h-[9rem] w-[9rem] -translate-x-1/2 -translate-y-1/2" viewBox="0 0 160 160" fill="none" height="160" width="160" xmlns="http://www.w3.org/2000/svg">
<path d="M130.912 130.912a71.997 71.997 0 0 0-10.911-110.778A71.999 71.999 0 0 0 9.383 94.046a72.004 72.004 0 0 0 19.705 36.866" stroke-width="16" stroke-linecap="round" stroke="#EEDC82"></path>
<path d="M146.65 52.764A72.004 72.004 0 0 0 69.647 8.748a71.998 71.998 0 0 0-40.559 122.164" class="duration-[1s] [stroke-dasharray:100] [stroke-dashoffset:-99] group-hover:[stroke-dashoffset:0]" pathLength="100" stroke-width="16" stroke-linecap="round" stroke="#B49A18"></path>
</svg>
<p class="text-[0.75rem] font-semibold">1729/2500 Steps</p>
</div>
// https://tailwindcss.com/docs/plugins#static-variants
// https://tallpad.com/series/tailwind/lessons/styling-vue-components-using-tailwindcss-custom-variants
// https://play.tailwindcss.com/8Pmxm8TomW
const plugin = require('tailwindcss/plugin')
/** @type {import('tailwindcss').Config} */
export default {
theme: {
extend: {
// ...
},
},
plugins: [
plugin(function ({ addVariant }) {
addVariant('hocus', ['&:hover', '&:focus'])
addVariant('error', ['&[data-error=true]', '[data-error=true] &'])
}),
],
}
<!--
https://github.com/tailwindlabs/tailwindcss-aspect-ratio/blob/master/src/index.js#L39
https://play.tailwindcss.com/4cuLPqCv05
https://www.youtube.com/watch?v=sxxUK0l8jKE
-->
<div class="p-20 flex justify-center items-center gap-12">
<img class="avatar-sm" src="https://res.cloudinary.com/thirus/image/upload/v1705061543/images/avatar.png" alt="" />
<img class="avatar" src="https://res.cloudinary.com/thirus/image/upload/v1705061543/images/avatar.png" alt="" />
<img class="avatar-lg" src="https://res.cloudinary.com/thirus/image/upload/v1705061543/images/avatar.png" alt="" />
<img class="avatar-xl" src="https://res.cloudinary.com/thirus/image/upload/v1705061543/images/avatar.png" alt="" />
</div>
<!-- https://play.tailwindcss.com/CF9WdM43Jf -->
<section class="bg-slate-900 min-h-screen text-slate-100">
<!-- Shopping Cart -->
<div class="rounded-md bg-slate-800 p-8 grid grid-cols-[auto_1fr_auto_auto_auto] gap-6">
<div class="grid gap-6 col-span-5 grid-cols-subgrid">
<p class="col-span-2">Product</p>
<p>Price</p>
<p>Quantity</p>
<p class="text-right">Total</p>
</div>
<div class="grid gap-6 col-span-5 grid-cols-subgrid">
<img
class="size-20 object-cover"
src="https://tinyurl.com/3r25tr36"
alt=""
/>
<div>
<h3 class="text-xl font-medium">
Stylish Tote Bag
</h3>
<p class="text-sm text-slate-400">
Women's Tote Bag Brown
</p>
<span class="text-sm text-slate-500">
#368798
</span>
</div>
<p class="text-slate-400">
$99.00
</p>
<label>
<input
class="border border-slate-600 bg-transparent px-2 py-1 text-sm text-slate-400"
type="text"
value="1"
size="2"
/>
</label>
<p class="font-medium text-right">
$99.00
</p>
</div>
<div class="grid gap-6 col-span-5 grid-cols-subgrid">
<img
class="size-20 object-cover"
src="https://tinyurl.com/3pj5teex"
alt=""
/>
<div>
<h3 class="text-xl font-medium">
Sunglasses
</h3>
<p class="text-sm text-slate-400">
Wooden Frame
</p>
<span class="text-sm text-slate-500">
#756328
</span>
</div>
<p class="text-slate-400">
$102.00
</p>
<label>
<input
class="border border-slate-600 bg-transparent px-2 py-1 text-sm text-slate-400"
type="text"
value="10"
size="2" />
</label>
<p class="font-medium text-right">
$1020.00
</p>
</div>
</div>
</section>