Skip to content

Instantly share code, notes, and snippets.

@danmatthews
Last active July 27, 2023 19:33
Show Gist options
  • Save danmatthews/f6ea70c3a1ef6348b38a5bd79ac1f6dd to your computer and use it in GitHub Desktop.
Save danmatthews/f6ea70c3a1ef6348b38a5bd79ac1f6dd to your computer and use it in GitHub Desktop.
// Add this to your 'plugins' array in your tailwind config file.
// This creates classes suffixed with an opacity level for each bg colour
// For example, .bg-red would have .bg-red-10 through .bg-red-100 for 0.10% opacity background and 100% opacity respectively.
({addUtilities, config}) => {
let colors = config('colors', []);
const newColors = {};
let hexToRgb = (hex) => {
var result = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex);
return result ? {
r: parseInt(result[1], 16),
g: parseInt(result[2], 16),
b: parseInt(result[3], 16)
} : null;
}
for ( i in colors) {
let c = hexToRgb(colors[i]);
if (c) {
let nms = {
'.1':'10',
'.2':'20',
'.3':'30',
'.4':'40',
'.5':'50',
'.6':'60',
'.7':'70',
'.8':'80',
'.9':'90',
'1.0':'100'
};
for (o in nms) {
newColors[`.bg-${i}-${nms[o]}`] = {
'background-color': `rgba(${c.r},${c.g},${c.b}, ${o})`
};
}
}
}
addUtilities(newColors);
}
@mxmtsk
Copy link

mxmtsk commented Jan 29, 2020

I have changed your code a little bit so that it takes care of sub values as well (for example bg-gray-500 will be bg-gray-500-10 for 10% opacity). Your code was a great help to get this done quick!

    function ({addUtilities, config, theme}) {
      let colors =  theme('colors', []);
      const newColors = {};
      const nms = {
        '.1':'10',
        '.2':'20',
        '.3':'30',
        '.4':'40',
        '.5':'50',
        '.6':'60',
        '.7':'70',
        '.8':'80',
        '.9':'90',
      };
      let hexToRgb = (hex) => {
        var result = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex);
        return result ? {
          r: parseInt(result[1], 16),
          g: parseInt(result[2], 16),
          b: parseInt(result[3], 16)
        } : null;
      }
      for (const [key, value] of Object.entries(colors)) {
        if (typeof value === 'string') {
          let c = hexToRgb(value);
          
          if (c !== null) {
            for (var o in nms) {
              newColors[`.bg-${key}-${nms[o]}`] = {
                'background-color': `rgba(${c.r},${c.g},${c.b}, ${o})`
              };
            }
          }
        } else {
          for (const [subKey, subValue] of Object.entries(value)) {
            let c = hexToRgb(subValue);

            if (c !== null) {
              for (var subO in nms) {
                newColors[`.bg-${key}-${subKey}-${nms[subO]}`] = {
                  'background-color': `rgba(${c.r},${c.g},${c.b}, ${o})`
                };
              }
            }
          }
        }
      }
      addUtilities(newColors);
    }

I also had to overwrite Tailwinds default values for black and white with hex codes instead of color names, otherwise it won't generate rgba classes for both cases because it can't be converted rgb values

@danmatthews
Copy link
Author

@mxmtsk awesome, had totally forgotten about this gist tbh! Thanks for keeping it alive.

@john-gold
Copy link

With mxmtsk's function I get css classes like

.bg-gray-100-10 {
  background-color: rgba(247,250,252, undefined);
}

so I changed var o in nms to const o in nms which reveals o is not defined in the latter else clauses

here is an adjusted version which also takes the variants into account

tailwind.config.js

const plugin = require('tailwindcss/plugin')

const rgba = ({ addUtilities, theme, variants }) => {
  const regex = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i
  const colors = theme('colors', [])
  const newColors = {}
  const nms = {
    '.1': '10',
    '.2': '20',
    '.3': '30',
    '.4': '40',
    '.5': '50',
    '.6': '60',
    '.7': '70',
    '.8': '80',
    '.9': '90'
  }
  const hexToRgb = (hex) => {
    const result = regex.exec(hex)
    return result ? {
      r: parseInt(result[1], 16),
      g: parseInt(result[2], 16),
      b: parseInt(result[3], 16)
    } : null
  }
  for (const [key, value] of Object.entries(colors)) {
    if (typeof value === 'string') {
      const c = hexToRgb(value)

      if (c !== null) {
        for (const [o, v] of Object.entries(nms)) {
          newColors[`.bg-${key}-${v}`] = {
            'background-color': `rgba(${c.r},${c.g},${c.b}, ${o})`
          }
        }
      }
    } else {
      for (const [subKey, subValue] of Object.entries(value)) {
        const c = hexToRgb(subValue)

        if (c !== null) {
          for (const [o, v] of Object.entries(nms)) {
            newColors[`.bg-${key}-${subKey}-${v}`] = {
              'background-color': `rgba(${c.r},${c.g},${c.b}, ${o})`
            }
          }
        }
      }
    }
  }
  addUtilities(newColors, {
    variants: variants('backgroundColor')
  })
}

module.exports = {
  // ...
  plugins: [
    plugin(rgba)
  ]
  // ...
}

@lpj145
Copy link

lpj145 commented Jun 12, 2021

const hexReg = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})/i

/**
 * Convert hex color to rgb
 * @param hex
 * @returns {{r: number, b: number, g: number}|null}
 */
function hexToRgb (hex) {
  const result = hexReg.exec(hex)
  return result ? {
    r: parseInt(result[1], 16),
    g: parseInt(result[2], 16),
    b: parseInt(result[3], 16)
  } : null
}

function mountRgbaString({ r, g, b, a }) {
  return `rgba(${r}, ${g}, ${b}, ${a})`
}

function makeRgbaColors(colors = {}, opacities = {}) {
  if (typeof colors !== 'object' || typeof opacities !== 'object') {
    return {}
  }

  return Object.keys(colors).reduce((newColors, colorName) => {
    const rgb = hexToRgb(colors[colorName])

    if (rgb === null) {
      return newColors
    }

    Object.keys(opacities).forEach((opacityAlias) => {
      rgb['a'] = opacities[opacityAlias]
      newColors[`:root`] = {
        ...newColors[':root'],
        [`--${colorName}-${opacityAlias}`]: mountRgbaString(rgb)
      }
      newColors[`.bg-${colorName}-${opacityAlias}`] = {
        'background-color': mountRgbaString(rgb)
      }
      newColors[`.text-${colorName}-${opacityAlias}`] = {
        'color': mountRgbaString(rgb)
      }
    })

    return newColors
  }, {})
}

function rgbaPlugin({ addUtilities, theme, variants }) {
  addUtilities(
    makeRgbaColors(
      theme('colors', {}),
      {
        '400': '.82',
        '300': '.45',
        '200': '.1',
        '100': '.04',
      },
    ), {
      variants: variants('backgroundColor')
    }
  )
}

module.exports = {
  rgbaPlugin
}

Improves, add text color, background color, custom properties, and accept params.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment