angle-uparrow-clockwisearrow-counterclockwisearrow-down-uparrow-leftatcalendarcard-listchatcheckenvelopefolderhouseinfo-circlepencilpeoplepersonperson-fillperson-plusphoneplusquestion-circlesearchtagtrashx

Create a colors class and color mapper for your application

The colors class uses 147 named colors recommended by the W3C and it is easy to add extra attributes to the colors.

27 November 2021 Updated 27 November 2021
In Other
post main image
https://pixabay.com/users/engin_akyurt-3656355/

I was implementing some charts with Chart.js and needed to pass colors from my Flask application to the template.
The graph is a line graph and the number of lines can vary. With the graph I also show a table with the (numeric) values used in the graph.

The lines have different colors, I choose them from a list of colors. The table of line values has a column for each line. I want the header cell of a column to be the same color as the line color.

This was the moment I thought to create a color class.

Color and color names

When I started I just picked some colors from an example I found. But at a certain point I wanted more flexibility. On the internet there is the 'CSS Color Module Level 3' specification, see links below, which gives you a list of 147 named colors, like:

  • aliceblue
  • antiquewhite
  • aqua
  • aquamarine
  • azure
  • beige
  • bisque
  • black
  • etc.

Nice.

The CSSColor class

I wanted my colors to be objects like:

  • css_colors.red
  • css_colors.skyblue

having attributes:

  • hex_code
  • rgb_code

In the Python code the color is used like:

css_colors.red.hex_code
css_colors.skyblue.hex_code

The two classes are:

class CSSColor:
    
    def __init__(
        self,
        name=None,
        hex_code=None,
        rgb_code=None,
    ):
        self.name = name
        self.hex_code = hex_code
        self.rgb_code = rgb_code

    def __repr__(self):
        return 'CSSColor({}, {}, {})'.format(self.name, self.hex_code, self.rgb_code)


class CSSColors:

    def __init__(
        self,
    ):
        self.colors = [
            # we put the colors here
            CSSColor( ... ),
            CSSColor( ... ),
            # more colors
            CSSColor( ... ),
        ]

        for color in colors:
            setattr(self, color.name, color)

Get the colors in our class

Go to the webpage mentioned above and copy all 147 color lines, by dragging the mouse over the list. Then paste this in your favorite editor. This looks like:

        aliceblue     #f0f8ff     240,248,255
        antiquewhite     #faebd7     250,235,215
        aqua     #00ffff     0,255,255
        aquamarine     #7fffd4     127,255,212
        ...
        yellow     #ffff00     255,255,0
        yellowgreen     #9acd32     154,205,50 

Now in your editor, use regular expressions to create the color classes. My editor is Geany and I use the following:

Search for:

^\s+(.*?)\s+(.*?)\s+(\d+),(\d+),(\d+)$

Replace with:

CSSColor(name='\1', hex_code='\2', rgb_code='rgb(\3, \4, \5)'),

The result:

CSSColor(name='aliceblue', hex_code='#f0f8ff', rgb_code='rgb(240, 248, 255)'),
CSSColor(name='antiquewhite', hex_code='#faebd7', rgb_code='rgb(250, 235, 215)'),
CSSColor(name='aqua', hex_code='#00ffff', rgb_code='rgb(0, 255, 255)'),
CSSColor(name='aquamarine', hex_code='#7fffd4', rgb_code='rgb(127, 255, 212)'),
...
CSSColor(name='yellow', hex_code='#ffff00', rgb_code='rgb(255, 255, 0)'),
CSSColor(name='yellowgreen', hex_code='#9acd32', rgb_code='rgb(154,205,50)'),

Now we copy this into the CSSColors class:

class CSSColors:

    def __init__(
        self,
    ):
        self.colors = [
            CSSColor(name='aliceblue', hex_code='#f0f8ff', rgb_code='rgb(240, 248, 255)'),
            CSSColor(name='antiquewhite', hex_code='#faebd7', rgb_code='rgb(250, 235, 215)'),
            CSSColor(name='aqua', hex_code='#00ffff', rgb_code='rgb(0, 255, 255)'),
            CSSColor(name='aquamarine', hex_code='#7fffd4', rgb_code='rgb(127, 255, 212)'),
            # more colors
            CSSColor(name='yellow', hex_code='#ffff00', rgb_code='rgb(255, 255, 0)'),
            CSSColor(name='yellowgreen', hex_code='#9acd32', rgb_code='rgb(154,205,50)'),
        ]
        for color in self.colors:
            # make color an attribute of this object
            setattr(self, color.name, color)

That's it. To use the colors we instantiate the object:

css_colors = CSSColors()

Of course we instantiate this object only once in our application. Now we can use the colors like:

css_colors.red
css_colors.red.hex_code

A chart with line colors

But we must do more. I want more flexibility and also add my own color names and color attributes. Instead of using red, blue, etc., I want color names like:

  • line1
  • line2
  • ...
  • line9

And I want to add class names I can refer to in my Jinja HTML templates. For this I use a base class:

css-class-background-<color>

and then add the color name to it. The class name becomes in this case:

css-class-background-line1

The AppColors class

For our application we create AppColor and AppColors classes. In the AppColors class we create line colors for the charts and we also add the css_class_background_color attribute to the line colors.

class AppColor(CSSColor):

    def __repr__(self):
        return 'AppColor({}, {}, {}, {})'.\
        format(self.name, self.hex_code, self.rgb_code, getattr(self, 'css_class_background_color', None))


class AppColors(CSSColors):

    def __init__(
        self,
        css_class_background_color_template=None,
    ):
        CSSColors.__init__(self)

        # use specified css_class or use default
        self.css_class_background_color_template = css_class_background_color_template or 'css-class-background-'

        # here we can change / add colors
        self.chart_line_colors = [
            self.new_app_color(name='line1', color=self.aqua),
            self.new_app_color(name='line2', color=self.yellow),
            # more colors
            self.new_app_color(name='line3', color=self.antiquewhite),
        ]

        # add the new colors to object
        for color in self.chart_line_colors:
            # add css class attribute to color
            setattr(color, 'css_class_background_color', self.css_class_background_color_template + color.name)
            # make color an attribute of this object
            setattr(self, color.name, color)

    def new_app_color(
        self,
        name=None,
        color=None,
    ):
        return AppColor(
            name=name or color.name,
            hex_code=color.hex_code,
            rgb_code=color.rgb_code,
        )

There is not really much magic here.

Using the colors

Examples of how to use the colors:

  • a css color
  • the colors list
  • a line color
  • the line colors list
app_colors = AppColors()

print('\nuse a css color:')
print('app_colors.aqua.hex_code = {}'.format(app_colors.aqua.hex_code))
print('app_colors.yellow.hex_code = {}'.format(app_colors.yellow.hex_code))

print('\nuse the colors list:')
for color in app_colors.colors:
    print('{}'.format(color))

print('\nuse a line color:')
print('app_colors.line2.hex_code = {}'.format(app_colors.line2.hex_code))
print('app_colors.line2.css_class_background_color = {}'.format(app_colors.line2.css_class_background_color))

print('\nuse the line colors list:')
for color in app_colors.chart_line_colors:
    print('{}'.format(color))

And the result is:

use a css color:
app_colors.aqua.hex_code = #00ffff
app_colors.yellow.hex_code = #ffff00

use the colors list:
CSSColor(aliceblue, #f0f8ff, rgb(240, 248, 255))
CSSColor(antiquewhite, #faebd7, rgb(250, 235, 215))
CSSColor(aqua, #00ffff, rgb(0, 255, 255))
CSSColor(aquamarine, #7fffd4, rgb(127, 255, 212))
CSSColor(yellow, #ffff00, rgb(255, 255, 0))
CSSColor(yellowgreen, #9acd32, rgb(154,205,50))

use a line color:
app_colors.line2.hex_code = #ffff00
app_colors.line2.css_class_background_color = css-class-background-line2

use the line colors list:
AppColor(line1, #00ffff, rgb(0, 255, 255), css-class-background-line1)
AppColor(line2, #ffff00, rgb(255, 255, 0), css-class-background-line2)
AppColor(line3, #faebd7, rgb(250, 235, 215), css-class-background-line3)

Note that the line colors have an extra attribute.

To generate the CSS style classes in the Jinja HTML template we must pass app_colors.chart_line_colors to the template:

return = render_template(
    ...
    chart_line_colors=app_colors.chart_line_colors    
)

In the template we iterate the colors:

<style>
{%- for color in chart_line_colors -%}
.{{ color.css_class_background_color }} {
    background-color: {{ color.hex_code }};
{%- endfor -%}
</style>

The result:

.css-class-background-line1 {
    background-color: #00ffff;
}
.css-class-background-line2 {
    background-color: #ffff00;
}
.css-class-background-line3 {
    background-color: #faebd7;
}

And then finally in our code when generating the chart table data for the line datasets we add the CSS classes of the line colors to the column headers.

Using the color class in Flask

When using this in Flask we modify our AppColors class and add a init_app() method.

class AppColors:

    def __init__(
        self,
        app=None,
    ):
        self.css_class_background_color_template = 'css-class-background-'

    def init_app(
        self,
        app=None,
        css_class_background_color_template=None,
    ):
    ...

Then in factory.py we do something like:

app_colors = AppColors()

def create_app():

    app = Flask()
    ...
    app_colors.init_app(app)

Now we can use the app_colors object in our application (you may want to make the app_colors object an attribute of the app object).

Blue is not blue

You might want to the use the AppColors class for other things like all your menus. Then you have a background color, text color, border color, etc. Usually you arrange this in CSS but you can also do this with the AppColor class.

Instead of using hardcoded values you define colors as above like:

  • menu_text_color
  • menu_background_color
  • menu_border_color

You can start with text color is black and later change this to red. In the AppColor class we map colors to our liking.

Summary

For my application with charts I wanted line colors that can be changed easily and also can be exported to the Jinja HTML template. First I scraped 147 colors from the webpage 'CSS Color Module Level 3' and created a CCSColors class. The next step was to create an AppColors class for my application. Here I added new named colors based on the CSSClass colors . I also added a (css_class) attribute to the new colors.

Links / credits

CSS Color Module Level 3
https://www.w3.org/TR/css-color-3

Read more

Colors

Leave a comment

Comment anonymously or log in to comment.

Comments

Leave a reply

Reply anonymously or log in to reply.