A closer look at CSS functions

Habdul Hazeez - Nov 23 '20 - - Dev Community

Introduction

CSS functions are used as properties for various CSS properties. In this article you'll learn about these functions, how they are used, when to use them, if necessary, their "backup" approach (if the specific function is not supported by the browser). You'll also get links to other writings from around the web for further study. In the end, you'll have added to your CSS skills.

CSS function definition

In most modern programming languages, a function is defined by writing the function keyword and specifying the name of the function followed by a pair of brackets (which can contain the function parameters), and curly that will contain the function definition.

An example of a function in JavaScript:

function helloWorld() {
    console.log("Hello world, I am a function");
}

// Call the function
helloWorld(); // Hello world, I am a function
Enter fullscreen mode Exit fullscreen mode

Unlike JavaScript (or other languages) where you can define some function(s) (as shown above) before you can call them, CSS functions definition are written by browser vendors, you just need to call the function with the appropriate property and then pass the necessary arguments.

The syntax is given below:

property-name: <function name>(arguments)
Enter fullscreen mode Exit fullscreen mode

Now, let's go into proper details and explanation. We will start by listing the functions followed by detailed explanation and code examples.

CSS functions

The functions are listed below, they are arranged based on the likelihood of their usage in your projects. Click on the function name to jump to its explanation and browser support:

You'll also find backup approach for RGB and HSL color functions and backup approach for CSS gradients.

In addition, the browser version under each browser support table is the first version of that browser to support that said property.

url()

The url() function name is short for Uniform Resource Locator. It is used with CSS properties that loads an external resource (like an image or font file) that is used on the web page. Examples of such properties are:

  • src
  • background-image

The location of the file(s) is either on your local machine, another server on the same network, or the internet. Then you will have to specify the URL in any of the following format:

  • Relative URL
  • Absolute URL
  • data-URI

Relative URL

A relative URL is used to reference file(s) that are in the same directory as the current working directory or in another directory on the same server. It is specified without the server address.

When the Relative URL is used with the url() function, it takes the following form if the file is in the same directory as the CSS file:

url('file-location');
Enter fullscreen mode Exit fullscreen mode

In the example below, CSS background-image property as indicated by the property name, is used to add a background image to a page. Here, the url() is using a Relative URL:

.hero-section {
    background-image: url('image.jpg');
}
Enter fullscreen mode Exit fullscreen mode

When the file is in a higher directory than the CSS file, you use .., which means go up one directory.

url('../file-location');
Enter fullscreen mode Exit fullscreen mode

In the example below, @font-face has a url() using a Relative URL that goes up one level to get the font file:

@font-face {
    font-family: "Catamaran-Bold";
    /**
     * Go up one level to the fonts folder and find the Catamaran
     * font inside the Catamaran folder.
     */
    src: url('../fonts/Catamaran/Catamaran-Bold.ttf') format('truetype');
}

/**
 * Now, the font can be used with the font-family property
 */
h1 {
    font-family: "Catamaran-Bold", Verdana, sans-serif;
}
Enter fullscreen mode Exit fullscreen mode

If it's two directory up, you'll write .. twice separated by /, which means go up one directory, and then another directory:

url('../../file-location');
Enter fullscreen mode Exit fullscreen mode

CSS code example for this format is given below, this time the URL goes up twice to fetch the image:

.hero-image {
    background-image: url(../../image.jpg);
}
Enter fullscreen mode Exit fullscreen mode

You should know that the double .. can be folder names

url('../my-assets/images/file-location')
Enter fullscreen mode Exit fullscreen mode

Therefore, you can have a code example like the following:

.hero-image {
    background-image: url(../my-assets/images/image.jpg);
}
Enter fullscreen mode Exit fullscreen mode

Absolute URL

An absolute URL is mostly used when referencing files on another server, but you can use it to reference files on your server. It takes the following form:

url('protocol://domain/path')
Enter fullscreen mode Exit fullscreen mode

The protocol can be any of the following:

  • http://
  • https://
  • ftp://
  • file://

When used with the url() function, it takes the following form:

url('https://server-address/path-to-file');
Enter fullscreen mode Exit fullscreen mode

In the following example, url() is using an Absolute URL to load the required resource for the .hero-section:

.hero-section {
    background-image: url('https://server-address/images/image.jpg')
}
Enter fullscreen mode Exit fullscreen mode

data-URI

A data-URI is used to specify a resource in base-64 format or Scalable Vector Graphics.

url('data:resource-format');
Enter fullscreen mode Exit fullscreen mode

The following example taken from MDN, is using a data-URI to fetch an SVG:

.background {
    background: yellow;
    background: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='90' height='45'%3E%3Cpath d='M10 10h60' stroke='%2300F' stroke-width='5'/%3E%3Cpath d='M10 20h60' stroke='%230F0' stroke-width='5'/%3E%3Cpath d='M10 30h60' stroke='red' stroke-width='5'/%3E%3C/svg%3E");
}
Enter fullscreen mode Exit fullscreen mode

Browser Support

Chrome Firefox Edge Opera Safari Internet Explorer
1 1 12 3.5 1 3

rgb()

This function name is taken from RGB which stands for Red, Green, and Blue. Therefore, this function defines a color using the RGB model.

It accepts three comma-separated values either as integer values between 0 and 255 or percentage values between 0 and 100%. These values specify the intensity of the color.

With the previous information, it's evident that rgb() only works with CSS properties that is used to apply color to a web page element. Examples of such properties are:

  • background-color
  • box-shadow

Its syntax is:

rgb(<red value>, <green value>, <blue value>);
Enter fullscreen mode Exit fullscreen mode

The color of box-shadow is specified using rgb():

.media-card {
    box-shadow: 0 2px 4px rgb(0, 0, 0); /* Black */
}
Enter fullscreen mode Exit fullscreen mode

You can rewrite the previous examples to use percentage values:

/**
 * Note the percentage values.
 */
.media-card {
    box-shadow: 0 2px 4px rgb(0%, 0%, 0%); /* Black */
}
Enter fullscreen mode Exit fullscreen mode

Browser Support

Chrome Firefox Edge Opera Safari Internet Explorer
1 1 4.0 3.5 1 11.0

rgba()

On a normal day, the background color of the next selector should be Black, but due to the alpha transparency value of 0, it turns out White.

/**
 * Note the alpha transparency value
 */
body {
  background-color: rgba(0, 0, 0, 0);
}
Enter fullscreen mode Exit fullscreen mode

Similar to rgb(), it works with CSS properties that applies colors to a web page element. An example is the background-color demonstrated above.

Browser Support

Chrome Firefox Edge Opera Safari Internet Explorer
1 3.0 9.0 10.0 3.1 11

hsl()

HSL stands for Hue Saturation Lightness which is another model for defining a color. The function hsl() defines colors using this model.

Its syntax is:

hsl(hue, saturation, lightness);
Enter fullscreen mode Exit fullscreen mode

Where:

  • hue — The degree of the color on a color wheel. The color wheel is a circle measured in 360deg. On the circle 0 (or 360) is Red, 120 is Green, 240 is Blue.
  • saturation — The intensity of the color where 0% represents shade of gray and 100% is the full color.
  • lightness — The value or tone of the color. 0% represents Black, 50% is normal, and 100% is White.

Let's create a variant of green color with a bit of lightness:

body {
    background-color: hsl(120, 20%, 70%);
}
Enter fullscreen mode Exit fullscreen mode

I'll advise that you should experiment with other values for better understanding and fun.

Browser Support

Chrome Firefox Edge Opera Safari Internet Explorer
1.0 1.0 9.0 9.5 3.1 9.0

hsla()

Same as hsl() with the addition of the alpha transparency. As a reminder, the alpha transparency specifies the opacity of the color.

body {
    background-color: hsla(120, 20%, 50%, 0.3); /* Super light green */
}
Enter fullscreen mode Exit fullscreen mode

Backup approach for RGB and HSL color functions

For browsers that do not support the RGB and HSL color functions, you can use hexadecimal notation or the direct color name in-place of these functions for properties that use them as part of the values:

.media-card {
    box-shadow: 0 2px 4px #000000; /* Black */
}
Enter fullscreen mode Exit fullscreen mode

But if you use any of the function to specify a color as such:

body {
    background-color: rgb(120%, 79%, 21%);
}
Enter fullscreen mode Exit fullscreen mode

You should provide the same color (or another) in a hexadecimal notation or its direct name as a value (or part of the value) of the property, afterwards, you declare the same property again using the RGB or HSL color functions, therefore, for browsers that do not support the RGB or HSL color functions, the cascade will kick in and the browser will use the latter declaration.

body {
    background-color: #ffc936;
    background-color: rgb(120%, 79%, 21%);
}
Enter fullscreen mode Exit fullscreen mode

attr()

The HTML attribute of an element are returned by the attr() function. Furthermore, you can attach or place this attribute on a selected element.

This function is mostly used with CSS content property.

/**
 * Insert the Image alt attribute after the
 * image itself.
 */
.media-card__image::after {
    content: attr(alt);
}
Enter fullscreen mode Exit fullscreen mode

The following example taken from W3Schools will insert the value of the href attribute after each link:

a:after {
  content: " (" attr(href) ")";
}
Enter fullscreen mode Exit fullscreen mode

Browser Support

Chrome Firefox Edge Opera Safari Internet Explorer
2 1.0 8.0 9.0 3.1 8.0

linear-gradient()

Gradients in CSS gives you the opportunity to display smooth transitions between two or more specified colors. There are two types:

  • Linear Gradients — Goes down/up/left/right/diagonally and represented by the linear-gradient() function (discussed next).
  • Radial Gradients — They are defined by their center and represented by radial-gradient() function.

This linear-gradient() function sets a linear gradient as the background image of the selected element. Its syntax is:

background-image: linear-gradient(direction, color-stop1, color-stop2, ...);
Enter fullscreen mode Exit fullscreen mode

The direction value can be any of the following:

Top to bottom (default)

The following example starts at the top and ends at the bottom. It starts Black, transitioning to White:

body {
    background-image: linear-gradient(black, white);
}
Enter fullscreen mode Exit fullscreen mode

Left to right

As the name indicates, the gradient starts goes from left to right using the following keywords:

  • to
  • right

The following gradient starts Blue, transitioning to Red.

body {
    background-image: linear-gradient(to right blue, red);
}
Enter fullscreen mode Exit fullscreen mode

Diagonal

You can create a gradient by stating the horizontal and vertical starting positions. In pseudo-code, some examples are:

  • to bottom right
  • to bottom left

The following gradients start at top left and ends at the bottom right.

body {
    background-image: linear-gradient(to bottom right blue, red);
}
Enter fullscreen mode Exit fullscreen mode

You can also use angles to specify the direction of the gradient, this gives you more control over the direction of the gradient:

  • 0deg is equivalent to to top
  • 90deg is equivalent to to right
  • 180deg is equivalent to to bottom

Code examples on how to do this is left as an exercise to the reader.

Note that you are not limited to just two colors, you can use multiple color stops as shown in the example below:

body {
    background-image: linear-gradient(to bottom right, blue, red, aqua);
}
Enter fullscreen mode Exit fullscreen mode

In addition, you can also specify the color using the rgba() function, then you can use the alpha transparency to create a fading effect. As stated earlier:

The transparency value is a number between 0.0 (fully transparent) and 1.0 (fully opaque).

body {
    background-image: linear-gradient(to bottom right, rgba(124,65,89,0), #1560bd, rgba(255,0,0,1));
}
Enter fullscreen mode Exit fullscreen mode

The #1560bd above is a hexadecimal color notation which is another way to specify the color. How will it look like in a browser? Well, if the webpage is blank (why would you have a blank page?), it might not look good:

A web page with linear gradient

If the web page contains enough content the effect might look compelling:

A data table with linear gradients

Browser Support

Chrome Firefox Edge Opera Safari Internet Explorer
26.0, 10.0 -webkit- 16.0, 3.6 -moz- 12.0 12.1, 11.1 -o- 6.1, 5.1 -webkit- 10.0

repeating-linear-gradient()

As the name implies, this function is used to repeat linear gradients.

Its syntax is as follows:

 background-image: repeating-linear-gradient(angle | to side-or-corner, color-stop1, color-stop2, ...);
Enter fullscreen mode Exit fullscreen mode

Where:

  • angle — Direction of the gradient from 0deg to 360deg, default is 180deg.
  • side-or-corner — Two keywords (both optional) that defines the starting-point of the gradient line. The first indicates the horizontal side (left or right) and the second indicates the vertical side (top or bottom).
  • color-stop1, color-stop2, ... — The colors you want to render smooth transitions among followed by an optional stop position which is a percentage value between 0% and 100% or a length along the gradient axis.

An example is given below:

/**
 * The gradient starts at 75deg and uses 3 color stops.
 * The second color covers just 7% along the gradient.
*/
body {
    background-image: repeating-linear-gradient(75deg, rgba(124,65,89,0), #1560bd 7%, rgba(255,0,0,1) 10%);
}
Enter fullscreen mode Exit fullscreen mode

Browser Support

Chrome Firefox Edge Opera Safari Internet Explorer
26.0, 10.0 -webkit- 16.0, 3.6 -moz- 12 12.1, 11.1 -o- 6.1, 5.1 -webkit 10.0

radial-gradient()

This function sets a radial gradient as the background image of a web page element. A radial gradient starts at the center of the selected element and you must define at least two color stops.

The syntax is:

 background-image: radial-gradient(shape size at position, start-color, ..., last-color);
Enter fullscreen mode Exit fullscreen mode

Where:

  • shape — The shape of the gradient. ellipse is the default, the other being a circle.
  • size — Size of the gradient with farthest-corner, closest-side, closest-corner, and farthest-side as possible values.
  • position — Position of the gradient. Default is center.
  • start-color, ..., last-color — The colors that you want to render smooth transitions along which is a color value followed by an optional stop position (a percentage value between 0% and 100% or a length along the gradient axis).

A basic example of a radial gradient with three color stops is given below:

body { 
    background-image: radial-gradient(#1560bd, #cccccc, #1a1a1a);
}
Enter fullscreen mode Exit fullscreen mode

In the code snippet above, the gradient starts with #1560bd (blue) at the center, followed by #cccccc (gray) around it, then #1a1a1a (black) completes the gradient. The result is an ellipse (which is the default) with three rings of colors as defined by the color stops.

You can change the ellipse if you want to. The code snippet below will result in a circle because we changed the shape of the gradient before defining the color stops:

body {
    background-image: radial-gradient(circle, #1560bd, #cccccc, #1a1a1a);
}
Enter fullscreen mode Exit fullscreen mode

Furthermore, you can also define the size of the gradient. The size determines how big or small the gradient will be from its center. When you use the value closest-side the gradient appear small at the center of the selected element.

body {
    background-image: radial-gradient(circle closest-side, #1560bd, #cccccc, #1a1a1a);
}
Enter fullscreen mode Exit fullscreen mode

You should experiment with other values, i.e. farthest-side, closest-corner e.t.c.

Currently, the gradient is at the center, you can move it to the left or right if you wish. If you'd like to move it to the left, you'll have to ensure the position value is less than 50%. In the snippet below, the gradient will appear to the left of the selected element because position is reduced to 26%:

body {
    background-image: radial-gradient(circle closest-side at 26%, #1560bd, #cccccc, #1a1a1a);
}
Enter fullscreen mode Exit fullscreen mode

If you'd like to move the gradient further to the right, increase the position value above 50%. Try 86%.

Mind you, the position value can be specified as two values, the first value represents the x-axis (horizontal) and the second value is the y-axis (vertical).

In the code snippet below, the gradient is moved 40% from the left of the selected element and 30% from the top:

body {
    background-image: radial-gradient(circle closest-side at 40% 30%, #1560bd, #cccccc, #1a1a1a);
}
Enter fullscreen mode Exit fullscreen mode

Browser Support

Chrome Firefox Edge Opera Safari Internet Explorer
26.0, 10.0 -webkit- 16.0, 3.6 -moz- 12 12.1, 11.6 -o- 6.1, 5.1 -webkit- 10.0

repeating-radial-gradient()

This function behaves similarly to radial-gradient()repeats the radial gradient with one exception — it repeats the radial gradient.

You can convert the last code example to use a repeating-radial-gradient():

body {
    background-image: repeating-radial-gradient(circle closest-side at 40% 30%, #1560bd, #cccccc, #1a1a1a);
}
Enter fullscreen mode Exit fullscreen mode

The gradient is now repeated until it fills the entire area of the selected element.

Browser Support

Chrome Firefox Edge Opera Safari Internet Explorer
26.0, 10.0 -webkit- 16.0, 3.6 -moz- 12 12.1, 11.1 -o- 6.1, 5.1 -webkit 10.0

Backup approach for CSS Gradients

Use background-color has a backup for browsers that might not support CSS gradients.

body {
    background-color: black;

    /* Specify CSS gradients here */
}
Enter fullscreen mode Exit fullscreen mode

cubic-bezier()

As the name implies, this function defines a Cubic Bézier curve. Wikipedia defines a Bézier curve as:

a parametric curve used in computer graphics and related fields.

A Bézier curve is defined by four points P0, P1, P2, P3 where P0 and P3 are the start and end points.

In CSS, these points are fixed coordinates where:

  • P0 is (0, 0) — initial time and initial state
  • P3 is (1, 1) — final time and final state

The cubic-bezier() function is used with animation related properties in CSS for defining the speed of the animation. Some of these properties are animation-timing-function and transition-timing-function. Its syntax is:

cubic-bezier(x1,y1,x2,y2);
Enter fullscreen mode Exit fullscreen mode

Where:

  • x1, y1, x2, y2 are required numerical values. x1 and x2 must be a number from 0 to 1.

The example below is a modified version of an example on W3schools, the animation will start slow and will speed up towards the end.

div {
    width: 100px;
    height: 100px;
    background: red;
    transition: width 2s;
    transition-timing-function: cubic-bezier(.32,.3,.9,.21)
}

div:hover {
    width: 300px;
}
Enter fullscreen mode Exit fullscreen mode

Here is the HTML (without the metadata):

<p>Hover over the div element below, to see the transition effect.</p>
<div></div>
Enter fullscreen mode Exit fullscreen mode

There is an online tool by Lea Verou used for creating the Bézier curve values. Visit it at cubic-bezier.com.

Browser Support

Chrome Firefox Edge Opera Safari Internet Explorer
4.0 4.0 12 10.5 3.1 10.0

calc()

The calc() function performs mathematical calculation using the expression it receives as an argument. This expression can be simple or complex if need be, as long as it's a valid expression, the function will compute it and the result will be used as the property value.

The syntax is:

calc(expression)
Enter fullscreen mode Exit fullscreen mode

In the example below, the font size is calculated using calc():

/**
 * 1rem is 16px,
 * 0.2em is (16px * 2) which is 3.2px
 * Finally, 16px + 3.2px gives 19.2px
 */
p {
    font-size: calc(1rem + 0.2em); 
}
Enter fullscreen mode Exit fullscreen mode

The calculation in the code snippet above assumes the browser default font size is 16px (this is easily changeable by the user).

Browser Support

Chrome Firefox Edge Opera Safari Internet Explorer
26.0, 19.0 -webkit- 16.0, 4.0 -moz- 12 15 7.0, 6.0 -webkit 9.0

var()

When you declare a CSS variable in your stylesheet, the var() function is used to insert the value of the variable later in the stylesheet.

Its syntax is:

var(name, value)
Enter fullscreen mode Exit fullscreen mode

Where:

  • name — Required. The name of the variable that must start with two dashes --.
  • value — Optional fallback value that is used when the variable is not found.

First declare the variable as global variable:

:root {
    --border-color: #1560bd;
    --background-color: #cccccc;
}
Enter fullscreen mode Exit fullscreen mode

Then you can use the variable value via the var() function:

main {
    border: 2px solid var(--border-color);
    background-color: var(--background-color);
}
Enter fullscreen mode Exit fullscreen mode

You can provide fallback values if the variable is not found:

main {
    border: 2px solid var(--border-color, #1560bd);
    background-color: var(--background-color, #cccccc);
}
Enter fullscreen mode Exit fullscreen mode

To make things easy, the fallback values are the variable values declared in the :root element. You can use other values depending on the theme of your website.

Browser Support

Chrome Firefox Edge Opera Safari Internet Explorer
49 31 15.0 36.0 9.1 No Support

min()

The min() function is part of CSS logical operators (others being max() and clamp()) that allows you to provide a list of values as arguments and the browser will determine which one is the smallest and it will use this as the actual value at any given time.

It allows you to specify multiple values as arguments but two values is easiest to understand. Take a look at the following code snippet:

main {
    width: min(1000px, 500px);
}
Enter fullscreen mode Exit fullscreen mode

Here, we have main width set to min(1000px, 500px), at any given time the browser will set the width of main as 500px because it's always smaller than 1000px.

Now, let's tweak the values:

main {
    width: min(1000px, 70%);
}
Enter fullscreen mode Exit fullscreen mode

Here, at a larger viewport that is more than 1000px, the browser will set the width of main as 1000px because at that point the width has exceeded what the browser will compute as 70% of the viewport and automatically 1000px becomes the minimum value and the browser will use it as the actual width of main.

Have a look at the following GIF and take note of the computed width:

Browser developer tools opened

I had to increase and decrease the zoom level so that you can notice when the browser sets the main width to 1000px.

At a smaller viewport, where 1000px is more than 70%, the browser will set the width as 70% because at that point 70% is the minimum value compared to 1000px.

With that out of the way, you should know that you can write min(1000px, 70%) as:

main {
    width: 70%;
    max-width: 1000px;
}
Enter fullscreen mode Exit fullscreen mode

Effectively this means max-width use min() behind the scenes. But which one should you go for? 2 lines of code with width and max-width or 1 line of code with min()? I'll leave that you.

Browser Support

Chrome Firefox Edge Opera Safari Internet Explorer
79 75 79 66 11.1 No Support

max()

This is the opposite of min(). As it selects the maximum value from the list of supplied arguments which the browser will use as the actual value.

Using our previous example, let's switch the function name to max():

main {
    width: max(1000px, 70%);
}
Enter fullscreen mode Exit fullscreen mode

Here, the width of main will be a minimum of 1000px, but as the computed value of 70% increases beyond 1000px the browser will always use that computed value as the actual width of main.

In the GIF below, 1000px is the minimum value therefore, the browser will use it at that viewport size, but when the zoom level is increased (thus imitating an increase in viewport size) the actual width of main starts to grow:

Browser developer tools opened

You should note that max(1000px, 70%) is almost the same as:

main {
    width: 1000px;
    min-width: 70%;
}
Enter fullscreen mode Exit fullscreen mode

This also means that min-width use max().

Please, note the following for min() and max():

  • The order in which you write the arguments does not matter, the functions will select either the smallest or largest value as the actual value of the property.
  • You can supply more than 2 values as the arguments for both functions.
  • min() allows you to impose a maximum value since it selects the smallest of values and the browser won't allow the value to exceed this value hence that is the maximum it will go.
  • max() allows you to impose a minimum value since it selects the biggest of values and the browser will use the smallest value first and if condition permits it will keep growing more than this minimum value.
  • You can perform mathematical calculation inside min() and max() without using calc(). e.g. min(1000px + 10px, 70%).

Now, the question is: What if you want a value in-between a maximum and minimum value? You'll have to resolve to clamp().

Browser Support

Chrome Firefox Edge Opera Safari Internet Explorer
79 75 79 66 11.1 No Support

clamp()

With the clamp function, you can set a minimum and maximum values and in-between those values, an ideal value. The browser will use the computed ideal value when it's larger than the minimum value but smaller than the maximum value.

This is effectively setting a width, min-width, and max-width property on an element all at once.

In the code example below, the browser will use 500px because its computed value is larger than 5em which is the minimum value but smaller than the maximum value of 50em:

main {
  width: clamp(5em, 500px, 50em);
}
Enter fullscreen mode Exit fullscreen mode

When you tweak the values as follows:

main {
  width: clamp(600px, 500px, 50em);
}
Enter fullscreen mode Exit fullscreen mode

Here, 600px is larger than the ideal value of 500px therefore, the browser will use it as the actual value of the width property.

You can write the previous code is:

main {
    width: 500px;
    min-width: 600px;
    max-width: 50em;
}
Enter fullscreen mode Exit fullscreen mode

Kindly note that the clamp() function accepts 3 values, anything less or more is invalid.

Browser Support

Chrome Firefox Edge Opera Safari Internet Explorer
79 75 79 66 13.1 No Support

Conclusion

In this article you've learned about CSS functions in great detail. I'll encourage you to experiment further to deepen your CSS skills. In a future article we'll look at some practical applications of some of these functions. Thanks for reading.

References

Further reading

Credits

All browser support table is courtesy of W3Schools and MDN.

Cover photo is by Maik Jonietz on Unsplash.

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .