npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

tailwind-extended-shadows

v0.4.1

Published

TailwindCSS utility classes for fine-grain control over box-shadows, including layers.

Downloads

4,412

Readme

Tailwind Extended Shadows

A TailwindCSS plugin that gives you fine-grain control over your box-shadows via simple utility classes (including magic utilities for auto-generating beautifully layered/stacked shadows).

Visual Demo Playground: https://play.tailwindcss.com/6rFqo93e6h

Table of Contents

Usage

1. Control box-shadow x & y offsets

Class Syntax: shadow-{x|y}-{theme.boxShadowOffset}

Description: Shifts the shadow's position in the direction you specify

Examples:

  • shadow-y-1 (pulls shadow downwards by theme.boxShadowOffset.1 units),
  • -shadow-y-2 (pulls shadow upwards by theme.boxShadowOffset.2 units),
  • shadow-x-px (pulls shadow to the right by 1px),
  • -shadow-x-[3px] (pulls shadow to the left by 3px via arbitrary values syntax)

Configure: Override/extend offset classes/values via tailwind.config.js > theme > extend > boxShadowOffset. Learn more about Tailwind theming here.

module.exports = {
  /* ... */
  theme: {
    boxShadowOffset: {
      px: "1px",
      0: "0",
      0.5: "0.125rem",
      1: "0.25rem",
      1.5: "0.375rem",
      2: "0.5rem",
      2.5: "0.625rem",
      3: "0.75rem",
      3.5: "0.875rem",
      4: "1rem",
      5: "1.25rem",
      6: "1.5rem",
      7: "1.75rem",
      8: "2rem",
    },
  },
};

2. Control box-shadow blur

Class Syntax: shadow-blur-{theme.boxShadowBlur}

Description: Controls the sharpness/softness of the shadow.

Examples:

  • shadow-blur-1 (blurs the shadow by theme.boxShadowBlur.1 units),
  • shadow-blur-2 (blurs the shadow by theme.boxShadowBlur.2 units),
  • shadow-blur-px (blurs the shadow by 1px),
  • shadow-blur-[3px] (blurs the shadow by 3px via arbitrary values syntax)

Configure: Override/extend blur classes/values via tailwind.config.js > theme > extend > boxShadowBlur.

module.exports = {
  /* ... */
  theme: {
    boxShadowBlur: {
      px: "1px",
      0: "0",
      0.5: "0.125rem",
      1: "0.25rem",
      1.5: "0.375rem",
      2: "0.5rem",
      2.5: "0.625rem",
      3: "0.75rem",
      3.5: "0.875rem",
      4: "1rem",
      5: "1.25rem",
      6: "1.5rem",
      7: "1.75rem",
      8: "2rem",
      9: "2.25rem",
      10: "2.5rem",
      11: "2.75rem",
      12: "3rem",
      14: "3.5rem",
      16: "4rem",
    },
  },
};

3. Control box-shadow spread

Class Syntax: shadow-spread-{theme.boxShadowSpread}

Description: Expands or contracts the shadow surface area omnidirectionally

Examples:

  • shadow-spread-1 (expands the shadow by theme.boxShadowSpread.1 units),
  • shadow-spread-2 (expands the shadow by theme.boxShadowSpread.2 units),
  • -shadow-spread-px (contracts the shadow by 1px),
  • -shadow-spread-[3px] (contracts the shadow by 3px via arbitrary values syntax)

Configure: Override/extend spread classes/values via tailwind.config.js > theme > extend > boxShadowSpread.

module.exports = {
  /* ... */
  theme: {
    boxShadowSpread: {
      px: "1px",
      0: "0",
      0.5: "0.125rem",
      1: "0.25rem",
      1.5: "0.375rem",
      2: "0.5rem",
      2.5: "0.625rem",
      3: "0.75rem",
      3.5: "0.875rem",
      4: "1rem",
    },
  },
};

4. Control box-shadow opacity

Class Syntax: shadow-opacity-{theme.boxShadowOpacity}

Description: Shadow colors are still controlled by the built-in shadow-{color}/{opacity} classes; however, there are scenarios where you may wish to override the opacity without redeclaring the color, in which case you can use the new shadow-opacity-* class.

Examples:

  • shadow-opacity-15 (sets shadow color opacity to 0.15),
  • shadow-opacity-0 (sets shadow color opacity to 0, i.e. fully transparent),
  • shadow-opacity-100 (sets shadow color opacity to 1, i.e. fully opaque),

Configure: Override/extend shadow opacity classes/values via tailwind.config.js > theme > extend > boxShadowOpacity.

module.exports = {
  /* ... */
  theme: {
    boxShadowOpacity: {
      0: "0",
      5: "5",
      10: "10",
      15: "15",
      /* ... */
      100: "100",
    },
  },
};

[!NOTE]
Tailwind's built-in shadow-{size} classes continue to work as is, applying their own default offset + blur + spread values. When present, the new offset/blur/spread classes simply override those defaults. A shadow-{size} class is actually still required to be used alongside the offset/blur/spread classes, otherwise the box-shadow property won't be set.

Shadow layering/stacking

Tailwind Extended Shadows provides a few utility classes to auto-generate shadow "layers" (i.e. shadows stacked on top of each other); layering shadows can help you achieve more realistic, smooth, and/or sharp shadows -- here's a good article that demonstrates its power.

1. Control the number of layers

Class Syntax: shadows-{theme.boxShadowLayers}

Description: Auto-generates the number of shadow layers specified (theme options default to between 2 and 8 layers). You must specify a "base" shadow using the built-in Tailwind shadow classes (optionally using the offset/blur/spread/opacity utilities described above); the additional shadow layers will be auto-generated based on the "base" shadow (with pure CSS, thanks to a combination of CSS custom properties + calc()).

Examples:

  • shadows-3 (generates 2 shadow layers in addition to the "base" layer),
  • shadows-5 (generates 4 shadow layers in addition to the "base" layer),

Configure: Override/extend shadows-* classes/values via tailwind.config.js > theme > extend > boxShadowLayers.

module.exports = {
  /* ... */
  theme: {
    boxShadowLayers: {
      2: "2",
      3: "3",
      4: "4",
      5: "5",
      6: "6",
      7: "7",
      8: "8",
    },
  },
};

2. Control how the layers "scale"

Class Syntax: shadows-scale-{theme.boxShadowLayersScale}

Description: By default, each generated layer uses the same x/y/blur/spread values as the "base" shadow -- i.e. the base shadow is simply repeated on top of itself, which isn't usually ideal. The shadows-scale-* utility provides a way to specify a "multiplier" to generate each layer's x/y/blur in a way that scales from smallest to biggest (note: spread stays the same across all layers, as scaling this value is almost never desirable in my experience).

Examples:

  • shadows-scale-2 -- multiplies the base x/y/blur values by 2 to the power of the current layer number; example output:
// using layer utilities "shadows-5 shadows-scale-2":
0px 1px 1px 0px rgb(0 0 0 / 0.1) // base values
0px 2px 2px 0px rgb(0 0 0 / 0.1) // base values * 2^1
0px 4px 4px 0px rgb(0 0 0 / 0.1) // base values * 2^2
0px 8px 8px 0px rgb(0 0 0 / 0.1) // base values * 2^3
0px 16px 16px 0px rgb(0 0 0 / 0.1) // base values * 2^4

Configure: Override/extend shadows-scale-* classes/values via tailwind.config.js > theme > extend > boxShadowLayersScale.

module.exports = {
  /* ... */
  theme: {
    boxShadowLayersScale: {
      1: "1",
      1.25: "1.25",
      1.5: "1.5",
      1.75: "1.75",
      /* ... */
      4.75: "4.75",
      5: "5",
    },
  },
};

3. Apply easing function to adjust how layers "scale"

Class Syntax: shadows-ease-{in,out}

Description: In addition to shadows-scale-*, you can specify an easing function to inject into the scaling math. This allows the shadow layers to scale in a more fluid/less linear way. Currently only supports "quadratic" easing (due to limitations in CSS' ability to do complex math).

Examples:

  • shadows-ease-in -- scales the shadow layers starting slowly and accelerating towards the end.
  • shadows-ease-out -- scales the shadow layers starting fast and decelerating towards the end.

Configure: Unfortunately this class group is not configurable via your Tailwind theme, as it requires writing unique JS for each variation to ensure proper easing math is applied.


Layering Tips

  • Adding layers darkens your shadows -- to counteract this, reduce your base shadow color opacity
  • Because layer scaling is based on the "base" shadow values, you'll usually want to keep your base shadow values on the small side; i.e. use shadow-sm rather than shadow-xl when pairing it with shadows-{2-8}
  • Sometimes there's no visible difference when applying the shadows-ease-{in,out} classes; their effect becomes more apparent when using higher base offset/blur and/or scaling values

Playground

Use the following Tailwind Playground to quickly test out these new shadow classes in real-time: https://play.tailwindcss.com/6rFqo93e6h

CSS Output:

Default output without tailwind-extended-shadows installed:

.shadow-lg {
  --tw-shadow: 0 10px 15px -3px rgb(0 0 0 / 0.1), 0 4px 6px -4px rgb(0 0 0 / 0.1);
  --tw-shadow-colored: 0 10px 15px -3px var(--tw-shadow-color), 0 4px 6px -4px
      var(--tw-shadow-color);
  box-shadow: var(--tw-ring-offset-shadow, 0 0 #0000), var(
      --tw-ring-shadow,
      0 0 #0000
    ), var(--tw-shadow);
}
.shadow-slate-900\/15 {
  --tw-shadow-color: rgb(15 23 42 / 0.15);
  --tw-shadow: var(--tw-shadow-colored);
}

With tailwind-extended-shadows installed:

.shadow-lg {
  /* The following CSS properties use the .shadow-lg default values */
  --tw-shadow-x-offset: 0px;
  --tw-shadow-y-offset: 4px;
  --tw-shadow-blur: 6px;
  --tw-shadow-spread: -4px;
  --tw-shadow-opacity: 1;
  --tw-shadow-layers: 0 0 #0000;
  --tw-shadows-multiplier: 1;
  --tw-shadow-layer-base: 0px 10px 15px -3px var(--tw-shadow-color, rgb(0 0 0 /
            0.1)), var(--tw-shadow-x-offset) var(--tw-shadow-y-offset) var(
        --tw-shadow-blur
      ) var(--tw-shadow-spread) var(--tw-shadow-color, rgb(0 0 0 / 0.1));
  --tw-shadow: var(--tw-shadow-layer-base);
  box-shadow: var(--tw-inset-shadow, 0 0 #0000), var(
      --tw-ring-offset-shadow,
      0 0 #0000
    ), var(--tw-ring-shadow, 0 0 #0000), var(--tw-shadow);
}
.shadow-slate-900\/15 {
  /* adds support for opacity and doesn't set `--tw-shadow` anymore due to re-structure */
  --tw-shadow-color: rgb(15 23 42 / var(--tw-shadow-opacity, 0.15));
  --tw-shadow-opacity: 0.15;
}
.shadow-y-2 {
  /* overrides the `--tw-shadow-y-offset` value set by `shadow-lg` */
  --tw-shadow-y-offset: 0.5rem;
}
.shadow-x-2 {
  /* overrides the `--tw-shadow-x-offset` value set by `shadow-lg` */
  --tw-shadow-x-offset: 0.5rem;
}
.-shadow-spread-2 {
  /* overrides the `--tw-shadow-spread` value set by `shadow-lg` */
  --tw-shadow-spread: -0.5rem;
}
.shadow-blur-4 {
  /* overrides the `--tw-shadow-blur` value set by `shadow-lg` */
  --tw-shadow-blur: 1rem;
}
.shadows-4 {
  --tw-shadows-multiplier: 1;
  --tw-shadow-layers: calc(
        var(--tw-shadow-x-offset) * var(--tw-shadows-multiplier)
      ) calc(var(--tw-shadow-y-offset) * var(--tw-shadows-multiplier)) calc(
        var(--tw-shadow-blur) * var(--tw-shadows-multiplier)
      ) var(--tw-shadow-spread) var(--tw-shadow-color, rgb(0 0 0 / 0.1)), calc(
        var(--tw-shadow-x-offset) * var(--tw-shadows-multiplier) * var(--tw-shadows-multiplier)
      ) calc(
        var(--tw-shadow-y-offset) * var(--tw-shadows-multiplier) * var(--tw-shadows-multiplier)
      )
      calc(
        var(--tw-shadow-blur) * var(--tw-shadows-multiplier) * var(--tw-shadows-multiplier)
      ) var(--tw-shadow-spread) var(--tw-shadow-color, rgb(0 0 0 / 0.1)),
    calc(
        var(--tw-shadow-x-offset) * var(--tw-shadows-multiplier) * var(
            --tw-shadows-multiplier
          ) * var(--tw-shadows-multiplier)
      ) calc(
        var(--tw-shadow-y-offset) * var(--tw-shadows-multiplier) * var(
            --tw-shadows-multiplier
          ) * var(--tw-shadows-multiplier)
      )
      calc(
        var(--tw-shadow-blur) * var(--tw-shadows-multiplier) * var(
            --tw-shadows-multiplier
          ) * var(--tw-shadows-multiplier)
      ) var(--tw-shadow-spread) var(--tw-shadow-color, rgb(0 0 0 / 0.1));
  --tw-shadow: var(--tw-shadow-layer-base), var(--tw-shadow-layers);
}
.shadows-4.shadows-ease-in {
  /* overrides the `--tw-shadow-layers` value set by `shadows-4`, applying extra "ease-in" math */
  --tw-shadow-layers: calc(
        calc(var(--tw-shadow-x-offset) * var(--tw-shadows-multiplier)) * 0.25 *
          0.25
      ) calc(
        calc(var(--tw-shadow-y-offset) * var(--tw-shadows-multiplier)) * 0.25 *
          0.25
      )
      calc(
        calc(var(--tw-shadow-blur) * var(--tw-shadows-multiplier)) * 0.25 * 0.25
      ) var(--tw-shadow-spread) var(--tw-shadow-color, rgb(0 0 0 / 0.1)), calc(
        calc(
            var(--tw-shadow-x-offset) * var(--tw-shadows-multiplier) * var(--tw-shadows-multiplier)
          ) * 0.5 * 0.5
      ) calc(
        calc(
            var(--tw-shadow-y-offset) * var(--tw-shadows-multiplier) * var(--tw-shadows-multiplier)
          ) * 0.5 * 0.5
      )
      calc(
        calc(
            var(--tw-shadow-blur) * var(--tw-shadows-multiplier) * var(--tw-shadows-multiplier)
          ) * 0.5 * 0.5
      ) var(--tw-shadow-spread) var(--tw-shadow-color, rgb(0 0 0 / 0.1)),
    calc(
        calc(
            var(--tw-shadow-x-offset) * var(--tw-shadows-multiplier) * var(
                --tw-shadows-multiplier
              ) * var(--tw-shadows-multiplier)
          ) * 0.75 * 0.75
      ) calc(
        calc(
            var(--tw-shadow-y-offset) * var(--tw-shadows-multiplier) * var(
                --tw-shadows-multiplier
              ) * var(--tw-shadows-multiplier)
          ) * 0.75 * 0.75
      )
      calc(
        calc(
            var(--tw-shadow-blur) * var(--tw-shadows-multiplier) * var(
                --tw-shadows-multiplier
              ) * var(--tw-shadows-multiplier)
          ) * 0.75 * 0.75
      ) var(--tw-shadow-spread) var(--tw-shadow-color, rgb(0 0 0 / 0.1));
}
.shadows-scale-3 {
  /* overrides the `--tw-shadows-multiplier` value set by `shadows-4` */
  --tw-shadows-multiplier: 3;
}

As you can see, Tailwind Extended Shadows will increase the size of your CSS ouput, especially when using a large amount of layers combined with the easing utilities -- but it's arguably a negligible difference in the grand scheme of things.

Install

npm i tailwind-extended-shadows

Then add the plugin to your tailwind.config.js:

// tailwind.config.js
module.exports = {
  /* --- */
  plugins: [require("tailwind-extended-shadows")],
};

tailwind-merge compatibility plugin

If you're using the wonderful tailwind-merge package to take care of removing conflicting Tailwind classes at runtime, make sure to use our withExtendedShadows compatibility plugin from the separate tailwind-extended-shadows-merge package; otherwise, the extra shadow utility classes will be considered conflicting and will get stripped out when they shouldn't.

import { extendTailwindMerge } from "tailwind-merge";
import { withExtendedShadows } from "tailwind-extended-shadows-merge";

export const twMerge = extendTailwindMerge(withExtendedShadows);

Made by Kaelan Smith