diff --git a/src/components/color-indicator.jsx b/src/components/color-indicator.jsx
index d04ea2bb..be5b784c 100644
--- a/src/components/color-indicator.jsx
+++ b/src/components/color-indicator.jsx
@@ -17,6 +17,7 @@ const ColorIndicatorComponent = props => (
         <Popover
             body={
                 <ColorPicker
+                    allowAlpha={props.allowAlpha}
                     color={props.color}
                     color2={props.color2}
                     gradientType={props.gradientType}
@@ -44,6 +45,7 @@ const ColorIndicatorComponent = props => (
 );
 
 ColorIndicatorComponent.propTypes = {
+    allowAlpha: PropTypes.bool,
     className: PropTypes.string,
     disabled: PropTypes.bool.isRequired,
     color: PropTypes.string,
diff --git a/src/components/color-picker/checkerboard.png b/src/components/color-picker/checkerboard.png
new file mode 100644
index 00000000..d85f2d58
Binary files /dev/null and b/src/components/color-picker/checkerboard.png differ
diff --git a/src/components/color-picker/color-picker.jsx b/src/components/color-picker/color-picker.jsx
index 398c5cc6..ab2f0cf5 100644
--- a/src/components/color-picker/color-picker.jsx
+++ b/src/components/color-picker/color-picker.jsx
@@ -19,12 +19,21 @@ import fillRadialIcon from './icons/fill-radial-enabled.svg';
 import fillSolidIcon from './icons/fill-solid-enabled.svg';
 import fillVertGradientIcon from './icons/fill-vert-gradient-enabled.svg';
 import swapIcon from './icons/swap.svg';
+import checkerboard from './checkerboard.png'
 import Modes from '../../lib/modes';
 
-const hsvToHex = (h, s, v) =>
+const hsvToHex = (h, s, v, alpha = 100) => {
+    // Scale alpha from [0, 100] to [0, 1]
+    const alphaNormalized = alpha / 100;
     // Scale hue back up to [0, 360] from [0, 100]
-    parseColor(`hsv(${3.6 * h}, ${s}, ${v})`).hex
-;
+    const color = parseColor(`hsv(${3.6 * h}, ${s}, ${v})`);
+    // Get the hex value without the alpha channel
+    const hex = color.hex;
+    // Calculate the alpha value in hex (0-255)
+    const alphaHex = Math.round(alphaNormalized * 255).toString(16).padStart(2, '0');
+    // Return the hex value with the alpha channel
+    return `${hex}${alphaHex}`;
+};
 
 const messages = defineMessages({
     swap: {
@@ -41,13 +50,16 @@ class ColorPickerComponent extends React.Component {
         for (let n = 100; n >= 0; n -= 10) {
             switch (channel) {
             case 'hue':
-                stops.push(hsvToHex(n, this.props.saturation, this.props.brightness));
+                stops.push(hsvToHex(n, this.props.saturation, this.props.brightness, this.props.alpha));
                 break;
             case 'saturation':
-                stops.push(hsvToHex(this.props.hue, n, this.props.brightness));
+                stops.push(hsvToHex(this.props.hue, n, this.props.brightness, this.props.alpha));
                 break;
             case 'brightness':
-                stops.push(hsvToHex(this.props.hue, this.props.saturation, n));
+                stops.push(hsvToHex(this.props.hue, this.props.saturation, n, this.props.alpha));
+                break;
+            case 'alpha':
+                stops.push(hsvToHex(this.props.hue, this.props.saturation, this.props.brightness, n));
                 break;
             default:
                 throw new Error(`Unknown channel for color sliders: ${channel}`);
@@ -63,7 +75,7 @@ class ColorPickerComponent extends React.Component {
         stops[0] += ` 0 ${halfHandleWidth}px`;
         stops[stops.length - 1] += ` ${CONTAINER_WIDTH - halfHandleWidth}px 100%`;
 
-        return `linear-gradient(to left, ${stops.join(',')})`;
+        return `linear-gradient(to left, ${stops.join(',')}), url("${checkerboard}")`;
     }
     render () {
         return (
@@ -245,13 +257,37 @@ class ColorPickerComponent extends React.Component {
                     </div>
                     <div className={styles.rowSlider}>
                         <Slider
-                            lastSlider
+                            lastSlider={!this.props.allowAlpha}
                             background={this._makeBackground('brightness')}
                             value={this.props.brightness}
                             onChange={this.props.onBrightnessChange}
                         />
                     </div>
                 </div>
+                {this.props.allowAlpha && (
+                    <div className={styles.row}>
+                        <div className={styles.rowHeader}>
+                            <span className={styles.labelName}>
+                                <FormattedMessage
+                                    defaultMessage="Opacity"
+                                    description="Label for the opacity component in the color picker"
+                                    id="paint.paintEditor.alpha"
+                                />
+                            </span>
+                            <span className={styles.labelReadout}>
+                                {Math.round(this.props.alpha)}
+                            </span>
+                        </div>
+                        <div className={styles.rowSlider}>
+                            <Slider
+                                lastSlider
+                                background={this._makeBackground('alpha')}
+                                value={this.props.alpha}
+                                onChange={this.props.onAlphaChange}
+                            />
+                        </div>
+                    </div>
+                )}
                 <div className={styles.swatchRow}>
                     <div className={styles.swatches}>
                         {this.props.mode === Modes.BIT_LINE ||
@@ -299,7 +335,9 @@ class ColorPickerComponent extends React.Component {
 }
 
 ColorPickerComponent.propTypes = {
+    allowAlpha: PropTypes.bool,
     brightness: PropTypes.number.isRequired,
+    alpha: PropTypes.number.isRequired,
     color: PropTypes.string,
     color2: PropTypes.string,
     colorIndex: PropTypes.number.isRequired,
@@ -310,6 +348,7 @@ ColorPickerComponent.propTypes = {
     mode: PropTypes.oneOf(Object.keys(Modes)),
     onActivateEyeDropper: PropTypes.func.isRequired,
     onBrightnessChange: PropTypes.func.isRequired,
+    onAlphaChange: PropTypes.func.isRequired,
     onChangeGradientTypeHorizontal: PropTypes.func.isRequired,
     onChangeGradientTypeRadial: PropTypes.func.isRequired,
     onChangeGradientTypeSolid: PropTypes.func.isRequired,
diff --git a/src/components/paint-editor/paint-editor.jsx b/src/components/paint-editor/paint-editor.jsx
index c94d3585..f1b53cad 100644
--- a/src/components/paint-editor/paint-editor.jsx
+++ b/src/components/paint-editor/paint-editor.jsx
@@ -88,10 +88,12 @@ const PaintEditorComponent = props => (
                             <FillColorIndicatorComponent
                                 className={styles.modMarginAfter}
                                 onUpdateImage={props.onUpdateImage}
+                                allowAlpha
                             />
                             {/* stroke */}
                             <StrokeColorIndicatorComponent
                                 onUpdateImage={props.onUpdateImage}
+                                allowAlpha
                             />
                             {/* stroke width */}
                             <StrokeWidthIndicatorComponent
diff --git a/src/containers/color-indicator.jsx b/src/containers/color-indicator.jsx
index 10b5faf0..bbb352dd 100644
--- a/src/containers/color-indicator.jsx
+++ b/src/containers/color-indicator.jsx
@@ -30,6 +30,16 @@ const makeColorIndicator = (label, isStroke) => {
             // Flag to track whether an svg-update-worthy change has been made
             this._hasChanged = false;
         }
+        componentDidMount () {
+            if (!this.props.allowAlpha) {
+                this.removeAlpha();
+            }
+        }
+        componentDidUpdate (prevProps) {
+            if (!this.props.allowAlpha && prevProps.allowAlpha) {
+                this.removeAlpha();
+            }
+        }
         componentWillReceiveProps (newProps) {
             const {colorModalVisible, onUpdateImage} = this.props;
             if (colorModalVisible && !newProps.colorModalVisible) {
@@ -38,6 +48,14 @@ const makeColorIndicator = (label, isStroke) => {
                 this._hasChanged = false;
             }
         }
+        removeAlpha() {
+            const parsedColor1 = parseColor(this.props.color)
+            if (parsedColor1?.hex)
+                this.props.onChangeColor(parsedColor1.hex.substr(0, 7), 0)
+            const parsedColor2 = parseColor(this.props.color2)
+            if (parsedColor2?.hex)
+                this.props.onChangeColor(parsedColor2.hex.substr(0, 7), 1)
+        }
         handleChangeColor (newColor) {
             // Stroke-selector-specific logic: if we change the stroke color from "none" to something visible, ensure
             // there's a nonzero stroke width. If we change the stroke color to "none", set the stroke width to zero.
diff --git a/src/containers/color-picker.jsx b/src/containers/color-picker.jsx
index 14110088..cdc29ba0 100644
--- a/src/containers/color-picker.jsx
+++ b/src/containers/color-picker.jsx
@@ -26,10 +26,19 @@ const colorStringToHsv = hexString => {
     return hsv;
 };
 
-const hsvToHex = (h, s, v) =>
+const hsvToHex = (h, s, v, alpha = 100) => {
+    // Scale alpha from [0, 100] to [0, 1]
+    const alphaNormalized = alpha / 100;
     // Scale hue back up to [0, 360] from [0, 100]
-    parseColor(`hsv(${3.6 * h}, ${s}, ${v})`).hex
-;
+    const color = parseColor(`hsv(${3.6 * h}, ${s}, ${v})`);
+    // Get the hex value without the alpha channel
+    const hex = color.hex;
+    // Calculate the alpha value in hex (0-255)
+    const alphaHex = Math.round(alphaNormalized * 255).toString(16).padStart(2, '0');
+    // Return the hex value with the alpha channel
+    return `${hex}${alphaHex}`;
+};
+
 
 // Important! This component ignores new color props except when isEyeDropping
 // This is to make the HSV <=> RGB conversion stable. The sliders manage their
@@ -46,16 +55,20 @@ class ColorPicker extends React.Component {
             'handleHueChange',
             'handleSaturationChange',
             'handleBrightnessChange',
+            'handleAlphaChange',
             'handleTransparent',
             'handleActivateEyeDropper'
         ]);
 
         const color = props.colorIndex === 0 ? props.color : props.color2;
         const hsv = this.getHsv(color);
+        const alpha = this.getAlpha(color);
+
         this.state = {
             hue: hsv[0],
             saturation: hsv[1],
-            brightness: hsv[2]
+            brightness: hsv[2],
+            alpha: alpha * 100
         };
     }
     componentWillReceiveProps (newProps) {
@@ -64,10 +77,13 @@ class ColorPicker extends React.Component {
         const colorSetByEyedropper = this.props.isEyeDropping && color !== newColor;
         if (colorSetByEyedropper || this.props.colorIndex !== newProps.colorIndex) {
             const hsv = this.getHsv(newColor);
+            const alpha = this.getAlpha(newColor);
+
             this.setState({
                 hue: hsv[0],
                 saturation: hsv[1],
-                brightness: hsv[2]
+                brightness: hsv[2],
+                alpha: alpha * 100
             });
         }
     }
@@ -77,6 +93,26 @@ class ColorPicker extends React.Component {
         return isTransparent || isMixed ?
             [50, 100, 100] : colorStringToHsv(color);
     }
+    getAlpha(color) {
+        // TODO: need to find a way to get the alpha from all kinds of color strings (rgb, rgba, hex, hex with alpha, etc.)
+        // parse-color returns a range of 0-255 for hex inputs, but 0-1 for any other input
+        // (for hex codes without an alpha value, parse-color returns an alpha of 1)
+        
+        if (!color) return 0; // transparent swatch
+
+        const result = parseColor(color)
+        if (!result?.rgba) return 1; // no alpha value
+
+        let alpha = result.rgba[3]
+
+        if (color.startsWith('#') && alpha !== 1) {
+            // We used a hex color, divide parse-color alpha value by 255
+
+            alpha = alpha / 255
+        }
+        
+        return alpha
+    }
     handleHueChange (hue) {
         this.setState({hue: hue}, () => {
             this.handleColorChange();
@@ -92,15 +128,24 @@ class ColorPicker extends React.Component {
             this.handleColorChange();
         });
     }
+    handleAlphaChange (alpha) {
+        this.setState({alpha: alpha}, () => {
+            this.handleColorChange();
+        });
+    }
     handleColorChange () {
         this.props.onChangeColor(hsvToHex(
             this.state.hue,
             this.state.saturation,
-            this.state.brightness
+            this.state.brightness,
+            this.state.alpha
         ));
     }
     handleTransparent () {
-        this.props.onChangeColor(null);
+        // TODO: UX - should this reset all sliders, or just the alpha?
+        this.setState({alpha: 0}, () => {
+            this.handleColorChange();
+        });
     }
     handleActivateEyeDropper () {
         this.props.onActivateEyeDropper(
@@ -123,7 +168,9 @@ class ColorPicker extends React.Component {
     render () {
         return (
             <ColorPickerComponent
+                allowAlpha={this.props.allowAlpha}
                 brightness={this.state.brightness}
+                alpha={this.state.alpha}
                 color={this.props.color}
                 color2={this.props.color2}
                 colorIndex={this.props.colorIndex}
@@ -136,6 +183,7 @@ class ColorPicker extends React.Component {
                 shouldShowGradientTools={this.props.shouldShowGradientTools}
                 onActivateEyeDropper={this.handleActivateEyeDropper}
                 onBrightnessChange={this.handleBrightnessChange}
+                onAlphaChange={this.handleAlphaChange}
                 onChangeGradientTypeHorizontal={this.handleChangeGradientTypeHorizontal}
                 onChangeGradientTypeRadial={this.handleChangeGradientTypeRadial}
                 onChangeGradientTypeSolid={this.handleChangeGradientTypeSolid}
@@ -152,6 +200,7 @@ class ColorPicker extends React.Component {
 }
 
 ColorPicker.propTypes = {
+    allowAlpha: PropTypes.bool,
     color: PropTypes.string,
     color2: PropTypes.string,
     colorIndex: PropTypes.number.isRequired,
diff --git a/src/containers/paint-editor.jsx b/src/containers/paint-editor.jsx
index cd3d944c..78beeff8 100644
--- a/src/containers/paint-editor.jsx
+++ b/src/containers/paint-editor.jsx
@@ -12,6 +12,7 @@ import UpdateImageHOC from '../hocs/update-image-hoc.jsx';
 
 import {changeMode} from '../reducers/modes';
 import {changeFormat} from '../reducers/format';
+import {changeFillColor} from '../reducers/fill-style';
 import {clearSelectedItems, setSelectedItems} from '../reducers/selected-items';
 import {deactivateEyeDropper} from '../reducers/eye-dropper';
 import {setTextEditTarget} from '../reducers/text-edit-target';
diff --git a/src/helper/tools/eye-dropper.js b/src/helper/tools/eye-dropper.js
index 44750915..fa5a1ba2 100644
--- a/src/helper/tools/eye-dropper.js
+++ b/src/helper/tools/eye-dropper.js
@@ -77,6 +77,7 @@ class EyeDropperTool extends paper.Tool {
             const r = colorInfo.color[0];
             const g = colorInfo.color[1];
             const b = colorInfo.color[2];
+            const a = colorInfo.color[3] / 255; // Normalize alpha to range [0, 1]
 
             // from https://github.com/LLK/scratch-gui/blob/77e54a80a31b6cd4684d4b2a70f1aeec671f229e/src/containers/stage.jsx#L218-L222
             // formats the color info from the canvas into hex for parsing by the color picker
@@ -84,7 +85,7 @@ class EyeDropperTool extends paper.Tool {
                 const hex = c.toString(16);
                 return hex.length === 1 ? `0${hex}` : hex;
             };
-            this.colorString = `#${componentToString(r)}${componentToString(g)}${componentToString(b)}`;
+            this.colorString = `#${componentToString(r)}${componentToString(g)}${componentToString(b)}${Math.round(a * 255).toString(16).padStart(2, '0')}`;
         }
     }
     getColorInfo (x, y, hideLoupe) {
diff --git a/src/lib/make-color-style-reducer.js b/src/lib/make-color-style-reducer.js
index db716979..fbad62bb 100644
--- a/src/lib/make-color-style-reducer.js
+++ b/src/lib/make-color-style-reducer.js
@@ -4,7 +4,7 @@ import {getColorsFromSelection, MIXED} from '../helper/style-path';
 import GradientTypes from './gradient-types';
 
 // Matches hex colors
-const hexRegex = /^#([0-9a-f]{3}){1,2}$/i;
+const hexRegex = /^#([0-9a-f]{3}){1,2}([0-9a-f]{2})?$/i;
 
 const isValidHexColor = color => {
     if (!hexRegex.test(color) && color !== null && color !== MIXED) {