Tailwindcss: [Feature Proposal] Coloured Box Shadow

Created on 13 Feb 2019  路  12Comments  路  Source: tailwindlabs/tailwindcss

Heya,

I think it'd be neat if box shadows worked with colour variations. I tried to reach for it for a hover state and really wished it was there.

Most helpful comment

Update:

If you find this thread, here is how the config should look:

module.exports = {
  theme: {
    extend: {
      boxShadow: {
        blue: '0 4px 14px 0 rgba(19, 51, 81, 0.39)',
      },
    },
  },
};

And then you can use it with shadow-blue.

All 12 comments

You can already generate all the box shadow utilities you need with the shadows key in the config:

  shadows: {
    'red': '0 2px 4px 0 rgba(255, 0, 0, 0.10)',
    'green': '0 2px 4px 0 rgba(0, 255, 0, 0.10)',
    'blue': '0 2px 4px 0 rgba(0, 0, 255, 0.10)',
    'custom-hex-color': '0 2px 4px 0 #af9cdd',
  },

Do you mean that you would like Tailwind to automatically generate shadow utilities based on the colors key? If so, I don't think that's a good idea for three reasons:

  1. There is no precedent for it; even the textColors, backgroundColors, and borderColors keys only generate utilities for the colors they contain (even though the default config file uses a single colors variable that it then assigns to textColors, backgroundColors, and borderColors).

  2. A box-shadow declaration has more than just a color; it also has offsets (x and y), optionally a blur radius, and optionally a spread radius as well. Unfortunately, there is no box-shadow-color property in CSS so you have to set all of these values even if you just want to change the color. Tailwind would have no way of knowing what to set them to for the colors defined in colors.

  3. It would generate a lot of classes that most people don't need by default because Tailwind comes with a pretty large color palette, increasing the file size of the CDN version considerably.

Yeah, I guess shadow-md-blue would look out of place compared to border border-blue, given shadow-md shadow-blue is not possible. You've got a point there.

Going to close this as not something I plan to add to the default config out of the box right now, but of course can add in your own config 馃憤 Can definitely see a use case for things like focus styles on different colored buttons for example.

As another person who reached for/wished for this functionality today, is it possible to generate color shadows based on the base box-shadow sizes determined by choice (rather than automatically)?

Could boxShadow be extended with a colors section where users could set a range box-shadow colors in reference to the main theme colors (or something similar), with boxShadow sizing being handled separately? I.e shadow-xl-blue would be generated if the boxShadow config was extended with the color blue.

For me personally, this would be more maintainable than hardcoding the rgba values into boxShadows as is currently done in the config. Currently assuming that users will only use black shadows seems limiting to me

What should I add in my config to get this?

I am looking for a coloured version of my own shadow shadow-blur, something like
shadow-blur-blue-500 which will equal to box-shadow: 0 0 5px 1px #4299E1;

Update:

If you find this thread, here is how the config should look:

module.exports = {
  theme: {
    extend: {
      boxShadow: {
        blue: '0 4px 14px 0 rgba(19, 51, 81, 0.39)',
      },
    },
  },
};

And then you can use it with shadow-blue.

Here's an example of adding all shadow variants for all colors in the new Tailwind UI:

let makeShadow = (name, rgb) => {
  let obj = {};

  obj[name + "-xs"] = `0 0 0 1px rgba(${rgb}, 0.05)`;
  obj[name + "-xs"] = `0 0 0 1px rgba(${rgb}, 0.05)`;
  obj[name + "-sm"] = `0 1px 2px 0 rgba(${rgb}, 0.05)`;
  obj[name] = `0 1px 3px 0 rgba(${rgb}, 0.1), 0 1px 2px 0 rgba(${rgb}, 0.06)`;
  obj[
    name + "-md"
  ] = `0 4px 6px -1px rgba(${rgb}, 0.1), 0 2px 4px -1px rgba(${rgb}, 0.06)`;
  obj[
    name + "-lg"
  ] = `0 10px 15px -3px rgba(${rgb}, 0.1), 0 4px 6px -2px rgba(${rgb}, 0.05)`;
  obj[
    name + "-xl"
  ] = `0 20px 25px -5px rgba(${rgb}, 0.1), 0 10px 10px -5px rgba(${rgb}, 0.04)`;
  obj[name + "-2xl"] = `0 25px 50px -12px rgba(${rgb}, 0.25)`;
  obj[name + "-inner"] = `inset 0 2px 4px 0 rgba(${rgb}, 0.06)`;
  return obj;
};

module.exports = {
  theme: {
    extend: {
      boxShadow: {
        ...makeShadow("cool-gray", "71, 85, 104"),
        ...makeShadow("gray", "75, 85, 98"),
        ...makeShadow("red", "223, 39, 44"),
        ...makeShadow("orange", "207, 57, 24"),
        ...makeShadow("yellow", "158, 88, 28"),
        ...makeShadow("green", "16, 122, 87"),
        ...makeShadow("teal", "13, 116, 128"),
        ...makeShadow("blue", "29, 100, 236"),
        ...makeShadow("indigo", "87, 81, 230"),
        ...makeShadow("purple", "125, 59, 236"),
        ...makeShadow("pink", "213, 34, 105")
      }
    }
  },
  variants: {},
  plugins: [require("@tailwindcss/ui")]
};

that will allow you to use shadow-blue-lg, for example

Thanks for the workarounds. I agree this should be in core.

This should be in core.

Here's an example of adding all shadow variants for all colors in the new Tailwind UI:

let makeShadow = (name, rgb) => {
  let obj = {};

  obj[name + "-xs"] = `0 0 0 1px rgba(${rgb}, 0.05)`;
  obj[name + "-xs"] = `0 0 0 1px rgba(${rgb}, 0.05)`;
  obj[name + "-sm"] = `0 1px 2px 0 rgba(${rgb}, 0.05)`;
  obj[name] = `0 1px 3px 0 rgba(${rgb}, 0.1), 0 1px 2px 0 rgba(${rgb}, 0.06)`;
  obj[
    name + "-md"
  ] = `0 4px 6px -1px rgba(${rgb}, 0.1), 0 2px 4px -1px rgba(${rgb}, 0.06)`;
  obj[
    name + "-lg"
  ] = `0 10px 15px -3px rgba(${rgb}, 0.1), 0 4px 6px -2px rgba(${rgb}, 0.05)`;
  obj[
    name + "-xl"
  ] = `0 20px 25px -5px rgba(${rgb}, 0.1), 0 10px 10px -5px rgba(${rgb}, 0.04)`;
  obj[name + "-2xl"] = `0 25px 50px -12px rgba(${rgb}, 0.25)`;
  obj[name + "-inner"] = `inset 0 2px 4px 0 rgba(${rgb}, 0.06)`;
  return obj;
};

module.exports = {
  theme: {
    extend: {
      boxShadow: {
        ...makeShadow("cool-gray", "71, 85, 104"),
        ...makeShadow("gray", "75, 85, 98"),
        ...makeShadow("red", "223, 39, 44"),
        ...makeShadow("orange", "207, 57, 24"),
        ...makeShadow("yellow", "158, 88, 28"),
        ...makeShadow("green", "16, 122, 87"),
        ...makeShadow("teal", "13, 116, 128"),
        ...makeShadow("blue", "29, 100, 236"),
        ...makeShadow("indigo", "87, 81, 230"),
        ...makeShadow("purple", "125, 59, 236"),
        ...makeShadow("pink", "213, 34, 105")
      }
    }
  },
  variants: {},
  plugins: [require("@tailwindcss/ui")]
};

Building on top of this, this is what I did.

{
  boxShadow: theme => ({
    xs: '0 0 0 1px rgba(0, 0, 0, 0.05)',
    sm: '0 1px 2px 0 rgba(0, 0, 0, 0.05)',
    default: '0 1px 3px 0 rgba(0, 0, 0, 0.1), 0 1px 2px 0 rgba(0, 0, 0, 0.06)',
    md: '0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -1px rgba(0, 0, 0, 0.06)',
    lg: '0 10px 15px -3px rgba(0, 0, 0, 0.1), 0 4px 6px -2px rgba(0, 0, 0, 0.05)',
    xl: '0 20px 25px -5px rgba(0, 0, 0, 0.1), 0 10px 10px -5px rgba(0, 0, 0, 0.04)',
    '2xl': '0 25px 50px -12px rgba(0, 0, 0, 0.25)',
    inner: 'inset 0 2px 4px 0 rgba(0, 0, 0, 0.06)',
    outline: '0 0 0 3px rgba(66, 153, 225, 0.5)',
    none: 'none',
    // Build on top of our existing colors
    ...Object.entries(theme('colors'))
      .map(([key, value]) => makeShadow(key, value))
      .reduce((acc, cur) => ({ ...acc, ...cur }), {}),
  }),
}

@cerino-ligutom Only works with strings. ie: black: '#000' Doesn't work with objects like primary: { 100: '#ff0', 200: '#f00' }

I see what you're doing though and might be able to get it working with objs as well.


My solution with objs as well:

const hexRgb = require('hex-rgb') // yarn add hex-rgb
const defaultTheme = require('tailwindcss/defaultTheme')

// https://github.com/tailwindcss/tailwindcss/issues/654#issuecomment-606746700
const makeShadow = (name, rgb) => {
    const obj = {}
    obj[`${name}-xs`] = `0 0 0 1px rgba(${rgb}, 0.05)`
    obj[`${name}-xs`] = `0 0 0 1px rgba(${rgb}, 0.05)`
    obj[`${name}-sm`] = `0 1px 2px 0 rgba(${rgb}, 0.05)`
    obj[name] = `0 1px 3px 0 rgba(${rgb}, 0.1), 0 1px 2px 0 rgba(${rgb}, 0.06)`
    obj[`${name}-md`] = `0 4px 6px -1px rgba(${rgb}, 0.1), 0 2px 4px -1px rgba(${rgb}, 0.06)`
    obj[`${name}-lg`] = `0 10px 15px -3px rgba(${rgb}, 0.1), 0 4px 6px -2px rgba(${rgb}, 0.05)`
    obj[`${name}-xl`] = `0 20px 25px -5px rgba(${rgb}, 0.1), 0 10px 10px -5px rgba(${rgb}, 0.04)`
    obj[`${name}-2xl`] = `0 25px 50px -12px rgba(${rgb}, 0.25)`
    obj[`${name}-inner`] = `inset 0 2px 4px 0 rgba(${rgb}, 0.06)`
    return obj
}

module.exports = {
    theme: {
        colors: {
            ...defaultTheme.colors,
            // Custom
            primary: {
                100: '#d2e1ed',
                200: '#a5c4dc',
                300: '#78a6ca',
                400: '#4b89b9',
                500: '#1e6ba7',
                600: '#185686',
                700: '#124064',
                800: '#0c2b43',
                900: '#061521',
            },
            font: {
                100: '#d6d7d7',
                200: '#adb0b0',
                300: '#848888',
                400: '#5b6161',
                500: '#323939',
                600: '#282e2e',
                700: '#1e2222',
                800: '#141717',
                900: '#0a0b0b',
            },
            danger: {
                100: '#ffd8d6',
                200: '#ffb1ac',
                300: '#fe8983',
                400: '#fe6259',
                500: '#fe3b30',
                600: '#cb2f26',
                700: '#98231d',
                800: '#661813',
                900: '#330c0a',
            },
        },

        // https://github.com/tailwindcss/tailwindcss/issues/654#issuecomment-619279397
        boxShadow: theme => {
            // Handle color objects as well
            const fresh = Object.values(
                Object.entries(theme('colors')).reduce((acc, curr) => {
                    const [k, v] = curr
                    if (typeof v === 'string' && v !== 'transparent' && v !== 'currentColor') {
                        const { red, green, blue } = hexRgb(v)
                        acc[k] = makeShadow(k, `${red}, ${green}, ${blue}`)
                    }
                    if (typeof v === 'object') {
                        Object.entries(v).forEach(([_k, _v]) => {
                            const { red, green, blue } = hexRgb(_v)
                            acc[`${k}-${_k}`] = makeShadow(
                                `${k}-${_k}`,
                                `${red}, ${green}, ${blue}`,
                            )
                        })
                    }
                    return acc
                }, {}),
            ).reduce((acc, cur) => ({ ...acc, ...cur }), {})

            return {
                xs: '0 0 0 1px rgba(0, 0, 0, 0.05)',
                sm: '0 1px 2px 0 rgba(0, 0, 0, 0.05)',
                default: '0 1px 3px 0 rgba(0, 0, 0, 0.1), 0 1px 2px 0 rgba(0, 0, 0, 0.06)',
                md: '0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -1px rgba(0, 0, 0, 0.06)',
                lg: '0 10px 15px -3px rgba(0, 0, 0, 0.1), 0 4px 6px -2px rgba(0, 0, 0, 0.05)',
                xl: '0 20px 25px -5px rgba(0, 0, 0, 0.1), 0 10px 10px -5px rgba(0, 0, 0, 0.04)',
                '2xl': '0 25px 50px -12px rgba(0, 0, 0, 0.25)',
                inner: 'inset 0 2px 4px 0 rgba(0, 0, 0, 0.06)',
                outline: '0 0 0 3px rgba(66, 153, 225, 0.5)',
                none: 'none',
                ...fresh,
            }
        },
    },
}

Produces shadows like:

.md\:shadow-shadow-primary-100-sm {
  box-shadow: 0 1px 2px 0 rgba(210, 225, 237, 0.05);
}
Was this page helpful?
0 / 5 - 0 ratings

Related issues

chasegiunta picture chasegiunta  路  3Comments

chintanbanugaria picture chintanbanugaria  路  3Comments

spyric picture spyric  路  3Comments

AlexVipond picture AlexVipond  路  3Comments

nternetinspired picture nternetinspired  路  3Comments