Skip to content

Instantly share code, notes, and snippets.

@danieliser
Last active February 27, 2024 23:11
Show Gist options
  • Star 52 You must be signed in to star a gist
  • Fork 6 You must be signed in to fork a gist
  • Save danieliser/b4b24c9f772066bcf0a6 to your computer and use it in GitHub Desktop.
Save danieliser/b4b24c9f772066bcf0a6 to your computer and use it in GitHub Desktop.
Convert Hex Color to rgba with opacity
/**
* ECMA2015
*/
function convertHex(hexCode, opacity = 1){
var hex = hexCode.replace('#', '');
if (hex.length === 3) {
hex = hex[0] + hex[0] + hex[1] + hex[1] + hex[2] + hex[2];
}
var r = parseInt(hex.substring(0,2), 16),
g = parseInt(hex.substring(2,4), 16),
b = parseInt(hex.substring(4,6), 16);
/* Backward compatibility for whole number based opacity values. */
if (opacity > 1 && opacity <= 100) {
opacity = opacity / 100;
}
return 'rgba('+r+','+g+','+b+','+opacity+')';
}
/**
* ECMA2016 / ES6
*/
const convertHexToRGBA = (hexCode, opacity = 1) => {
let hex = hexCode.replace('#', '');
if (hex.length === 3) {
hex = `${hex[0]}${hex[0]}${hex[1]}${hex[1]}${hex[2]}${hex[2]}`;
}
const r = parseInt(hex.substring(0, 2), 16);
const g = parseInt(hex.substring(2, 4), 16);
const b = parseInt(hex.substring(4, 6), 16);
/* Backward compatibility for whole number based opacity values. */
if (opacity > 1 && opacity <= 100) {
opacity = opacity / 100;
}
return `rgba(${r},${g},${b},${opacity})`;
};
describe('convertHexToRGBA', () => {
test('accepts a hex value of 6 numbers and returns a rgba color string', () => {
expect(convertHexToRGBA('#F3F3F3')).toBe('rgba(243,243,243,1)')
})
test('accepts a hex value of 6 numbers with opacity of 1 and returns same color string', () => {
expect(convertHexToRGBA('#000', 1)).toBe(convertHexToRGBA('#000'))
})
test('accepts a hex value of 6 numbers with opacity and returns a rgba color string', () => {
expect(convertHexToRGBA('#000', 0.5)).toBe('rgba(0,0,0,0.5)')
})
test('accepts a hex value of 3 numbers and returns a rgba color string', () => {
expect(convertHexToRGBA('#aaa')).toBe('rgba(170,170,170,1)')
})
test('accepts a hex value of 3 numbers with opacity and returns a rgba color string', () => {
expect(convertHexToRGBA('#aaa', 0.5)).toBe('rgba(170,170,170,0.5)')
})
test('accepts a hex value of 3 numbers with opacity of 1 and returns same color string', () => {
expect(convertHexToRGBA('#aaa', 1)).toBe(convertHexToRGBA('#aaa', 1))
})
})
@onassar
Copy link

onassar commented Sep 20, 2015

Great thanks :)

@eflowbeach
Copy link

Nice!

@klosowsk
Copy link

Great!!

@haingdc
Copy link

haingdc commented Sep 19, 2019

nice!!

@jacobdo2
Copy link

Nice, great, thanks!

@Deltarios
Copy link

Thank you! :)

@Jmzp
Copy link

Jmzp commented Apr 24, 2020

Thanks!

Now with ES6

const convertHexToRGBA = (hex, opacity) => {
  const tempHex = hex.replace('#', '');
  const r = parseInt(tempHex.substring(0, 2), 16);
  const g = parseInt(tempHex.substring(2, 4), 16);
  const b = parseInt(tempHex.substring(4, 6), 16);

  return `rgba(${r},${g},${b},${opacity / 100})`;
};

@danieliser
Copy link
Author

@Jmzp - Updated to include both, thanks.

@roynwang
Copy link

roynwang commented Jul 9, 2020

To support the 3-digits hex(#333, #666)

const convertHexToRGBA = (hex, opacity) => {
    let tempHex = hex.replace('#', '')
    if (tempHex.length === 3) {
        tempHex += tempHex
    }
    const r = parseInt(tempHex.substring(0, 2), 16)
    const g = parseInt(tempHex.substring(2, 4), 16)
    const b = parseInt(tempHex.substring(4, 6), 16)

    return `rgba(${r},${g},${b},${opacity / 100})`
}

@danieliser
Copy link
Author

@roynwang - Great addition, updated.

@bryjch
Copy link

bryjch commented Jul 19, 2020

Hey, I'm fairly sure the solution for 3 digit hex isn't correct, as they actually represent #RRGGBB not #RGBRGB.

Two options I thought of - but there might be cleaner ways.

  1. Change the hex assignment:
if (hex.length === 3) {
  hex = `${hex[0]}${hex[0]}${hex[1]}${hex[1]}${hex[2]}${hex[2]}`
}

OR

  1. Conditional parseInt substring positions:
let r, g, b

if (hex.length === 3) {
  r = parseInt(hex.substring(0, 1), 16)
  g = parseInt(hex.substring(1, 2), 16)
  b = parseInt(hex.substring(2, 3), 16)
}
else {
  r = parseInt(hex.substring(0, 2), 16)
  g = parseInt(hex.substring(2, 4), 16)
  b = parseInt(hex.substring(4, 6), 16)
}

@danieliser
Copy link
Author

@bryjch - Updated, thanks for the tip.

@mg98
Copy link

mg98 commented Aug 13, 2020

line 22 should be let

@danieliser
Copy link
Author

@mg98 - Ugg, you are correct. Par for the course updating the code only here on a Gist.

@vladyn
Copy link

vladyn commented Aug 26, 2020

Awesome helper - many thanks! It saved me from adding third party color transformations library.

@mitramejia
Copy link

mitramejia commented Jan 20, 2021

Scrapped a unit test in a few mins, in case it helps someone. More/better test cases are welcome


describe('convertHexToRGBA', () => {
  test('accepts a hex value of 6 numbers and returns a rgba color string', () => {
    expect(convertHexToRGBA('#F3F3F3')).toBe('rgba(243,243,243,1)')
  })
  
  test('accepts a hex value of 6 numbers with opacity of 1 and returns same color string', () => {
    expect(convertHexToRGBA('#000', 1)).toBe(convertHexToRGBA('#000'))
  })
  
  test('accepts a hex value of 6 numbers with opacity and returns a rgba color string', () => {
    expect(convertHexToRGBA('#000', 0.5)).toBe('rgba(0,0,0,0.5)')
  })
  
  test('accepts a hex value of 3 numbers and returns a rgba color string', () => {
    expect(convertHexToRGBA('#aaa')).toBe('rgba(170,170,170,1)')
  })
  
  test('accepts a hex value of 3 numbers with opacity and returns a rgba color string', () => {
    expect(convertHexToRGBA('#aaa', 0.5)).toBe('rgba(170,170,170,0.5)')
  })
  
  test('accepts a hex value of 3 numbers with opacity of 1 and returns same color string', () => {
    expect(convertHexToRGBA('#aaa', 1)).toBe(convertHexToRGBA('#aaa', 1))
  })
})

@AKJPLAY
Copy link

AKJPLAY commented Sep 1, 2021

very nice and useful thank you very much.

@danieliser
Copy link
Author

@mitramejia - Thanks, added a new tests.js file to the gist.

@netnichaa
Copy link

Omg thank you so much. You saved my day. 🙏🏻

@MrMightyNighty
Copy link

The tests won't work with the current code since the converter doesn't have a default value for the opacity and the opacity is divided by 100 so you won't get the proper values if you use 0 - 1.

const convertHexToRGBA = (hexCode, opacity = 1) => {
    let hex = hexCode.replace('#', '');
    
    if (hex.length === 3) {
        hex = `${hex[0]}${hex[0]}${hex[1]}${hex[1]}${hex[2]}${hex[2]}`;
    }    
    
    const r = parseInt(hex.substring(0, 2), 16);
    const g = parseInt(hex.substring(2, 4), 16);
    const b = parseInt(hex.substring(4, 6), 16);

    return `rgba(${r},${g},${b},${opacity})`;
};

If you want to use it with with the division:

  • change the default value of opacity to 100
  • change tests
describe('convertHexToRGBA', () => {
  test('accepts a hex value of 6 numbers and returns a rgba color string', () => {
    expect(convertHexToRGBA('#F3F3F3')).toBe('rgba(243,243,243,100)')
  })
  
  test('accepts a hex value of 6 numbers with opacity of 1 and returns same color string', () => {
    expect(convertHexToRGBA('#000', 100)).toBe(convertHexToRGBA('#000'))
  })
  
  test('accepts a hex value of 6 numbers with opacity and returns a rgba color string', () => {
    expect(convertHexToRGBA('#000', 50)).toBe('rgba(0,0,0,50)')
  })
  
  test('accepts a hex value of 3 numbers and returns a rgba color string', () => {
    expect(convertHexToRGBA('#aaa')).toBe('rgba(170,170,170,100)')
  })
  
  test('accepts a hex value of 3 numbers with opacity and returns a rgba color string', () => {
    expect(convertHexToRGBA('#aaa', 50)).toBe('rgba(170,170,170,50)')
  })
  
  test('accepts a hex value of 3 numbers with opacity of 1 and returns same color string', () => {
    expect(convertHexToRGBA('#aaa', 100)).toBe(convertHexToRGBA('#aaa', 100))
  })
})

@seandaniel
Copy link

Thank you friend! 🙏

@danieliser
Copy link
Author

@MrMightyNighty - Thanks for the tip. Updated to include change to decimal based parameters, but also added a backward compatibility layer so it should theoretically work both ways, as long as you don't expect 0.9/100 to work without using pure 0.009, but I don't see that happening.

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