Thursday

19-06-2025 Vol 19

Build a Streamlit App to Find the Closest CSS Color Name Using Python 🎨✨

Build a Streamlit App to Find the Closest CSS Color Name Using Python 🎨✨

Have you ever struggled to find the perfect CSS color name for your web design? Do you have a specific color in mind but can’t quite pinpoint its closest named equivalent? This blog post will guide you through building a Streamlit app that effortlessly identifies the closest CSS color name to any color you input, all powered by Python! We’ll explore the underlying algorithms, the Streamlit framework, and how to create a user-friendly interface that delivers instant color name suggestions. Get ready to enhance your color workflow and boost your design precision!

Table of Contents

  1. Introduction: The Color Naming Problem and Streamlit’s Solution
  2. Understanding Color Spaces: RGB, Hex, and Beyond
  3. The Algorithm: Measuring Color Distance
    1. Euclidean Distance in RGB Space
    2. Optimizations and Considerations
  4. Setting Up Your Python Environment
    1. Installing Required Libraries: Streamlit, webcolors
    2. Creating a Virtual Environment (Optional but Recommended)
  5. Implementing the Color Matching Logic in Python
    1. Loading CSS Color Names and Hex Codes
    2. The `closest_colour` Function: Finding the Nearest Match
    3. Handling Edge Cases and Errors
  6. Building the Streamlit App: User Interface and Interactivity
    1. Creating the Main Application Layout
    2. Input Methods: Color Picker and Hex Code Input
    3. Displaying the Closest Color Name and Hex Code
    4. Adding Error Handling and User Feedback
  7. Enhancements and Future Features
    1. Adding Support for Other Color Spaces (HSL, HSV)
    2. Implementing a Color Palette Generator
    3. Improving the Algorithm for Perceptual Accuracy
  8. Deploying Your Streamlit App
    1. Deploying to Streamlit Cloud
    2. Sharing Your App with the World
  9. Conclusion: Color Naming Made Easy

1. Introduction: The Color Naming Problem and Streamlit’s Solution

Choosing the right colors for a website or application is crucial for creating a visually appealing and engaging user experience. While designers often have a specific color in mind, finding its exact CSS name can be surprisingly difficult. Relying solely on visual inspection or manually searching through lists of color names is time-consuming and prone to errors. This is where our Streamlit app comes in! By leveraging the power of Python and the simplicity of Streamlit, we can create a tool that automates this process, instantly identifying the closest CSS color name to any given color.

Streamlit is an open-source Python library that makes it incredibly easy to build and share custom web apps for machine learning and data science. It’s perfect for quickly prototyping ideas and sharing your work with others. In this tutorial, we’ll harness Streamlit’s intuitive API to create a user-friendly interface where users can input a color (either through a color picker or a hex code) and instantly see the closest matching CSS color name. This app streamlines the color selection process, saves time, and ensures consistency in your designs.

2. Understanding Color Spaces: RGB, Hex, and Beyond

Before diving into the code, it’s essential to understand the different ways colors are represented in digital systems. The most common color spaces are:

  • RGB (Red, Green, Blue): This is an additive color model where colors are created by combining different intensities of red, green, and blue light. Each component typically ranges from 0 to 255. For example, rgb(255, 0, 0) represents pure red.
  • Hexadecimal (Hex): This is a shorthand representation of RGB colors, commonly used in web development. A hex code consists of a ‘#’ symbol followed by six hexadecimal digits (0-9 and A-F). Each pair of digits represents the intensity of red, green, and blue, respectively. For example, #FF0000 represents pure red.
  • HSL (Hue, Saturation, Lightness): This color model represents colors in terms of hue (the color’s position on the color wheel), saturation (the color’s intensity), and lightness (the color’s brightness).
  • HSV (Hue, Saturation, Value): Similar to HSL, HSV represents colors in terms of hue, saturation, and value (brightness).

For this project, we’ll primarily be working with RGB and Hex color representations. We’ll use the webcolors library to convert between these formats and to access a list of CSS color names and their corresponding hex codes.

3. The Algorithm: Measuring Color Distance

The core of our app is the algorithm that determines the “closest” CSS color name to a given color. This involves calculating the distance between colors in a color space and selecting the color with the smallest distance.

3.1 Euclidean Distance in RGB Space

The most straightforward way to measure the distance between two colors is to calculate the Euclidean distance in RGB space. Imagine RGB as a three-dimensional space where the red, green, and blue components are the x, y, and z axes, respectively. Each color can be represented as a point in this space. The Euclidean distance between two colors (R1, G1, B1) and (R2, G2, B2) is calculated as:

distance = sqrt((R2 - R1)^2 + (G2 - G1)^2 + (B2 - B1)^2)

A smaller distance indicates that the two colors are more similar.

Example:

Let’s say we want to find the distance between rgb(255, 0, 0) (red) and rgb(255, 100, 0) (orange). The distance would be:

distance = sqrt((255 - 255)^2 + (100 - 0)^2 + (0 - 0)^2) = sqrt(10000) = 100

This distance provides a numerical measure of how different the two colors are.

3.2 Optimizations and Considerations

While Euclidean distance is a good starting point, it’s important to consider some optimizations and limitations:

  • Perceptual Uniformity: Euclidean distance in RGB space doesn’t perfectly correlate with human perception of color difference. Colors that are equidistant in RGB space might not appear equally different to the human eye. More sophisticated color spaces like CIELAB (L*a*b*) are designed to be perceptually uniform, meaning that equal distances in the space correspond to equal perceived color differences. However, for this introductory project, we’ll stick with RGB due to its simplicity and ease of implementation.
  • Performance: For a large number of CSS color names, calculating the Euclidean distance to each one can be computationally expensive. Consider using techniques like k-d trees or ball trees to speed up the nearest neighbor search. However, for the relatively small number of CSS color names, the performance impact of a simple linear search is negligible.

4. Setting Up Your Python Environment

Before we start coding, we need to set up our Python environment and install the necessary libraries.

4.1 Installing Required Libraries: Streamlit, webcolors

We’ll be using two libraries:

  • Streamlit: For building the web application interface.
  • webcolors: For accessing CSS color names and converting between color formats.

You can install these libraries using pip:

pip install streamlit webcolors

4.2 Creating a Virtual Environment (Optional but Recommended)

It’s generally good practice to create a virtual environment for each Python project. This helps to isolate your project’s dependencies and avoid conflicts with other projects. You can create a virtual environment using the following commands:

python -m venv myenv

source myenv/bin/activate (on Linux/macOS)

myenv\Scripts\activate (on Windows)

Replace “myenv” with your desired environment name. After activating the virtual environment, install the required libraries as described above.

5. Implementing the Color Matching Logic in Python

Now, let’s write the Python code that will find the closest CSS color name.

5.1 Loading CSS Color Names and Hex Codes

The webcolors library provides a convenient way to access CSS color names and their corresponding hex codes. We can use the CSS3_HEX_TO_NAMES dictionary to load this information.


from webcolors import CSS3_HEX_TO_NAMES, hex_to_rgb
from math import sqrt

def get_color_data():
    """
    Returns a dictionary mapping hex codes to CSS3 color names.
    """
    return CSS3_HEX_TO_NAMES

color_names = get_color_data()

5.2 The `closest_colour` Function: Finding the Nearest Match

Now, let’s define a function that takes an RGB tuple as input and returns the closest CSS color name.


def closest_colour(requested_colour):
    """
    Finds the closest CSS3 color name to a given RGB color.

    Args:
        requested_colour: A tuple representing the RGB color (e.g., (255, 0, 0)).

    Returns:
        The name of the closest CSS3 color and the corresponding hex code.
    """
    min_colours = {}
    for hex_code, color_name in color_names.items():
        r_c, g_c, b_c = hex_to_rgb(hex_code)
        rd = (r_c - requested_colour[0]) ** 2
        gd = (g_c - requested_colour[1]) ** 2
        bd = (b_c - requested_colour[2]) ** 2
        min_colours[(rd + gd + bd)] = color_name

    closest_name = min_colours[min(min_colours.keys())]
    closest_hex = next(key for key, value in color_names.items() if value == closest_name)

    return closest_name, closest_hex

This function iterates through all the CSS color names, calculates the Euclidean distance between the input color and each CSS color, and returns the name of the color with the smallest distance.

Explanation:

  • The function takes an RGB tuple requested_colour as input.
  • It iterates through the color_names dictionary (hex codes to color names).
  • For each CSS color, it converts the hex code to an RGB tuple using hex_to_rgb.
  • It calculates the squared Euclidean distance between the input color and the CSS color. Using squared distance avoids the expensive `sqrt` operation.
  • It stores the squared distance as the key and the color name as the value in the min_colours dictionary.
  • Finally, it finds the minimum distance in the min_colours dictionary and returns the corresponding color name. It also finds the corresponding hex code using a generator expression.

5.3 Handling Edge Cases and Errors

It’s important to handle potential edge cases and errors in our code. For example, we should ensure that the input color is a valid RGB tuple. While Streamlit’s color picker helps ensure valid inputs, handling invalid hex codes is still beneficial.


def get_color_name(requested_colour):
    """
    Gets the closest color name. Handles ValueErrors if the color is invalid.

    Args:
        requested_colour: An RGB tuple.

    Returns:
        A tuple: (color name, hex code). Returns ("Unknown", "#000000") on error.
    """
    try:
        closest_name, closest_hex = closest_colour(requested_colour)
        return closest_name, closest_hex
    except ValueError:
        return "Unknown", "#000000"

6. Building the Streamlit App: User Interface and Interactivity

Now, let’s build the Streamlit app that provides a user-friendly interface for our color matching logic.

6.1 Creating the Main Application Layout

We’ll start by creating the main layout of our Streamlit app. This will include a title, a color input, and a display area for the closest color name and hex code.


import streamlit as st

st.title("Closest CSS Color Name Finder 🎨")

# Input methods will go here
# Output display will go here

6.2 Input Methods: Color Picker and Hex Code Input

We’ll provide two input methods: a color picker and a hex code input field. This allows users to input colors in their preferred format.


color_input_method = st.radio(
    "Choose input method:",
    ("Color Picker", "Hex Code Input"),
    horizontal=True
)

if color_input_method == "Color Picker":
    color = st.color_picker("Pick a color:", "#00f") # Default to blue
    requested_color = tuple(int(color.lstrip("#")[i:i+2], 16) for i in (0, 2, 4))

elif color_input_method == "Hex Code Input":
    hex_code = st.text_input("Enter hex code:", "#00f")
    try:
        requested_color = tuple(int(hex_code.lstrip("#")[i:i+2], 16) for i in (0, 2, 4))
    except ValueError:
        st.error("Invalid hex code. Please enter a valid 6-digit hex code (e.g., #FF0000).")
        requested_color = None  # Set to None to avoid errors later
else:
    requested_color = None

Explanation:

  • We use st.radio to create a radio button group that allows users to choose between the color picker and hex code input.
  • If the user chooses the color picker, we use st.color_picker to display a color picker widget. The default color is set to blue (#00f). The `color` variable will store the hex code of the selected color. We convert the hex code to an RGB tuple using a list comprehension.
  • If the user chooses hex code input, we use st.text_input to display a text input field. We attempt to convert the hex code to an RGB tuple. If the hex code is invalid, we display an error message using st.error and set `requested_color` to None to prevent errors later.

6.3 Displaying the Closest Color Name and Hex Code

Now that we have the input color, we can use our get_color_name function to find the closest CSS color name and display it in the app.


if requested_color: #Only proceed if a valid color has been input
    closest_name, closest_hex = get_color_name(requested_color)

    st.write(f"Closest color name: **{closest_name}**")
    st.write(f"Hex code: **{closest_hex}**")

    # Display a colored box
    st.markdown(
        f"""
        
{closest_name}
""", unsafe_allow_html=True, )

Explanation:

  • We call the get_color_name function with the input color to get the closest CSS color name and its hex code.
  • We use st.write to display the color name and hex code in the app. We use Markdown formatting (**) to make the text bold.
  • We use st.markdown to display a colored box with the closest color. We use inline CSS to style the box with the background color, padding, text color, and font weight. unsafe_allow_html=True is required to allow Streamlit to render the HTML code. This is safe in this case because we are only using the hex code to set the background color.

6.4 Adding Error Handling and User Feedback

Let’s add some error handling and user feedback to make the app more robust and user-friendly.


# Error handling is already included in the hex code input
# and get_color_name functions

# Optional:  Add a message if no color is selected
if 'requested_color' not in locals() or requested_color is None:
    st.info("Please pick a color or enter a hex code to find the closest CSS color name.")

Complete Code:


import streamlit as st
from webcolors import CSS3_HEX_TO_NAMES, hex_to_rgb
from math import sqrt

def get_color_data():
    """
    Returns a dictionary mapping hex codes to CSS3 color names.
    """
    return CSS3_HEX_TO_NAMES

color_names = get_color_data()

def closest_colour(requested_colour):
    """
    Finds the closest CSS3 color name to a given RGB color.

    Args:
        requested_colour: A tuple representing the RGB color (e.g., (255, 0, 0)).

    Returns:
        The name of the closest CSS3 color and the corresponding hex code.
    """
    min_colours = {}
    for hex_code, color_name in color_names.items():
        r_c, g_c, b_c = hex_to_rgb(hex_code)
        rd = (r_c - requested_colour[0]) ** 2
        gd = (g_c - requested_colour[1]) ** 2
        bd = (b_c - requested_colour[2]) ** 2
        min_colours[(rd + gd + bd)] = color_name

    closest_name = min_colours[min(min_colours.keys())]
    closest_hex = next(key for key, value in color_names.items() if value == closest_name)

    return closest_name, closest_hex

def get_color_name(requested_colour):
    """
    Gets the closest color name. Handles ValueErrors if the color is invalid.

    Args:
        requested_colour: An RGB tuple.

    Returns:
        A tuple: (color name, hex code). Returns ("Unknown", "#000000") on error.
    """
    try:
        closest_name, closest_hex = closest_colour(requested_colour)
        return closest_name, closest_hex
    except ValueError:
        return "Unknown", "#000000"

st.title("Closest CSS Color Name Finder 🎨")

color_input_method = st.radio(
    "Choose input method:",
    ("Color Picker", "Hex Code Input"),
    horizontal=True
)

if color_input_method == "Color Picker":
    color = st.color_picker("Pick a color:", "#00f") # Default to blue
    requested_color = tuple(int(color.lstrip("#")[i:i+2], 16) for i in (0, 2, 4))

elif color_input_method == "Hex Code Input":
    hex_code = st.text_input("Enter hex code:", "#00f")
    try:
        requested_color = tuple(int(hex_code.lstrip("#")[i:i+2], 16) for i in (0, 2, 4))
    except ValueError:
        st.error("Invalid hex code. Please enter a valid 6-digit hex code (e.g., #FF0000).")
        requested_color = None  # Set to None to avoid errors later
else:
    requested_color = None

if requested_color: #Only proceed if a valid color has been input
    closest_name, closest_hex = get_color_name(requested_color)

    st.write(f"Closest color name: **{closest_name}**")
    st.write(f"Hex code: **{closest_hex}**")

    # Display a colored box
    st.markdown(
        f"""
        
{closest_name}
""", unsafe_allow_html=True, ) # Optional: Add a message if no color is selected if 'requested_color' not in locals() or requested_color is None: st.info("Please pick a color or enter a hex code to find the closest CSS color name.")

7. Enhancements and Future Features

Our Streamlit app is already functional, but we can enhance it with additional features and improvements.

7.1 Adding Support for Other Color Spaces (HSL, HSV)

Currently, our app only works with RGB colors. We can extend it to support other color spaces like HSL and HSV. This would require converting the input color to RGB before calculating the distance. The colorsys module in Python provides functions for converting between different color spaces.

Example (converting HSL to RGB):


import colorsys

def hsl_to_rgb(h, s, l):
  """Converts HSL values to RGB values."""
  r, g, b = colorsys.hls_to_rgb(h, l, s)
  return int(r * 255), int(g * 255), int(b * 255)

# Example usage:
hsl_color = (0.5, 1.0, 0.5) # Cyan in HSL
rgb_color = hsl_to_rgb(*hsl_color)
print(rgb_color) # Output: (0, 255, 255)

You could add a dropdown to your Streamlit app to let users choose the color space they want to use.

7.2 Implementing a Color Palette Generator

We could add a feature that generates a color palette based on the input color. This could include complementary colors, analogous colors, and triadic colors. This would require using color theory principles to calculate the different color variations.

7.3 Improving the Algorithm for Perceptual Accuracy

As mentioned earlier, Euclidean distance in RGB space doesn’t perfectly correlate with human perception of color difference. We could improve the algorithm by using a perceptually uniform color space like CIELAB (L*a*b*). This would require installing the colormath library and implementing the color space conversions.

8. Deploying Your Streamlit App

Now that our Streamlit app is complete, we can deploy it to share it with the world!

8.1 Deploying to Streamlit Cloud

Streamlit Cloud is a free and easy way to deploy your Streamlit apps. To deploy your app, follow these steps:

  1. Create a GitHub repository: Create a GitHub repository for your Streamlit app.
  2. Push your code to GitHub: Push your Python code and any other necessary files (e.g., a requirements.txt file) to your GitHub repository. The `requirements.txt` file should list all the dependencies for your app (streamlit, webcolors). You can create this file by running `pip freeze > requirements.txt` in your virtual environment.
  3. Sign up for Streamlit Cloud: Go to streamlit.io/cloud and sign up for a Streamlit Cloud account.
  4. Create a new app: Click on the “New app” button and select your GitHub repository and branch.
  5. Configure your app: Specify the main Python file (e.g., app.py) and click “Deploy!”.

Streamlit Cloud will automatically build and deploy your app. Once the deployment is complete, you’ll get a public URL that you can share with others.

8.2 Sharing Your App with the World

Once your app is deployed, you can share the public URL with anyone you want. You can also embed your app in a website or blog post.

9. Conclusion: Color Naming Made Easy

In this blog post, we’ve built a Streamlit app that effortlessly identifies the closest CSS color name to any color you input. We’ve explored the underlying algorithms, the Streamlit framework, and how to create a user-friendly interface. This app can streamline your color selection process, save time, and ensure consistency in your designs.

By leveraging the power of Python and the simplicity of Streamlit, you can create a wide range of data-driven web applications. This project is just a starting point, and we encourage you to experiment with different features and improvements to create your own unique color tools.

Now go forth and create beautiful, consistently colored designs!

“`

omcoding

Leave a Reply

Your email address will not be published. Required fields are marked *