FireBrick Custom CSS: Difference between revisions
m (→Base64-encoded data: line breaks - wording) |
|||
(38 intermediate revisions by 2 users not shown) | |||
Line 1: | Line 1: | ||
== Specifying custom CSS in the XML config file == |
|||
⚫ | |||
You can use custom CSS to override that used by the FireBrick’s own admin webpages to customise or enhance the UI to suit your particular needs or create your own look. A user's CSS override file is specified by a URI in the XML config in an attribute on the <code><http></code> element: |
|||
<syntaxhighlight lang=xml> |
|||
You can use custom css to override the css used on the FireBrick admin pages to create your own look. |
|||
⚫ | |||
⚫ | |||
</syntaxhighlight> |
|||
The css file is set in the config in the <http section: |
|||
⚫ | |||
⚫ | |||
Successfully implementing your own CSS customisations will involve studying the existing base CSS and XHTML files in your Firebrick. Be aware that because of CSS rules concerning specificity (see below) your own settings may sometimes not take precedence over the values given in the base CSS. To address this you will have to write rules that fit in with the existing structure of both the various CSS and XHTML files and add or successfully override property assignments. The latter is achieved by taking a close look at particular CSS selectors that are used in the base .css files. Detailed tips are given in later sections. |
|||
== Example - changing colours == |
|||
For example, to change the header and footer bar from red to blue, create your myfb.css file as: |
For example, to change the header and footer bar from red to blue, create your myfb.css file as: |
||
Line 16: | Line 18: | ||
div.header { |
div.header { |
||
background: inherit; |
|||
⚫ | |||
background: -moz-linear-gradient( top, #000080 0px, #202080 100% ); |
|||
⚫ | |||
background: -webkit-gradient( linear, top, bottom, color-stop( 0%, #000080 ), color-stop( 100%, #202080 ) ); |
|||
background: -webkit-linear-gradient( top, #000080 0%, #202080 100% ); |
|||
background: -o-linear-gradient( top, #000080 0%, #202080 100% ); |
|||
background: -ms-linear-gradient( top, #000080 0%, #202080 100% ); |
|||
background: linear-gradient( top, #000080 0%, #202080 100% ); |
|||
-ms-filter: "progid:DXImageTransform.Microsoft.gradient( startColorstr = '#000080', endColorstr = '#202080' )"; |
|||
-ms-filter: "progid:DXImageTransform.Microsoft.gradient(startColorstr='#000080', endColorstr='#202080')"; |
|||
} |
} |
||
div.footer { |
div.footer { |
||
background: inherit; |
|||
⚫ | |||
background: -moz-linear-gradient( top, #000080 0px, #202080 100% ); |
|||
⚫ | |||
background: -webkit-gradient( linear, left top, left bottom, color-stop( 0%, #000080 ), color-stop( 100%, #202080 ) ); |
|||
background: -webkit-linear-gradient( top, #000080 0%, #202080 100% ); |
|||
background: -o-linear-gradient( top, #000080 0%, #202080 100% ); |
|||
background: -ms-linear-gradient( top, #000080 0%, #202080 100% ); |
|||
background: linear-gradient( top, #000080 0%, #202080 100% ); |
|||
-ms-filter: "progid:DXImageTransform.Microsoft.gradient( startColorstr = '#000080', endColorstr = '#202080' )"; |
|||
-ms-filter: "progid:DXImageTransform.Microsoft.gradient(startColorstr='#000080', endColorstr='#202080')"; |
|||
} |
} |
||
</syntaxhighlight> |
</syntaxhighlight> |
||
⚫ | |||
Image of the resulting header, showing colour change: |
|||
<hr style="clear:both;color:inherit;background-color:inherit;margin:0 0 -2em" /> |
|||
== Example - changing font size == |
== Example - changing font size == |
||
The following example CSS greatly reduces the font sizes in use in the Firebrick's web pages |
The following example fragment of CSS greatly reduces the font sizes in use in the Firebrick's web pages: |
||
<syntaxhighlight lang=css> |
<syntaxhighlight lang=css> |
||
@media screen |
@media screen |
||
{ |
{ |
||
div.main, div.sidemenu div.menu a |
div.main, div.sidemenu div.menu a, div.topmenu, textarea |
||
{ |
{ |
||
font-size:x-small |
font-size: x-small |
||
} |
|||
div.footer |
|||
{ |
|||
padding: 2px 10px 1px |
|||
} |
|||
div.footer * |
|||
{ |
|||
vertical-align: top |
|||
} |
} |
||
} |
} |
||
</syntaxhighlight> |
</syntaxhighlight> |
||
Note that there is no space after the dot in <code>div.main</code> etc. This is essential; adding white space at this point would alter the meaning - see [https://www.w3.org/TR/CSS22/selector.html CSS selectors]. |
|||
'''Note:''' The above brief example is known to currently produce certain '''defects''' in the webpages’ layout: A known minor issue is that the vertical layout of the objects within the footer is slightly off. |
|||
At the time of writing, the shipping CSS in the Firebrick FB2500 was v1.45.001 Ximenes, and the standard <code>font-size:</code> value in use was keyword <code>small</code>. This could possibly change in future. |
|||
To ''increase'' the text size, this example would require a rewrite and lots of testing trial and error. Unfortunately changing text sizes can have a lot of nasty knock-on effects on layout, which cascade out of control in ways that are hard to predict. Hacks such as the above are likely to fall apart if the base CSS changes or if other aspects of the design cause the layout to change. This is in part because this is an override on parts of the base CSS, effectively a patch, and the user CSS has intimate dependencies on the precise base CSS content. Also there are dependencies between the (X)HTML and the CSS, so changes to the pages’ content or structure can possibly cause problems. |
|||
=== CSS debugging tips === |
|||
There are many powerful tools available for debugging CSS. When developing an ''override'' such as this, problems with the CSS [https://www.w3.org/TR/CSS22/cascade.html#specificity specificity rules] may mean that your property overrides do not take effect, as they do not ‘win’ over the specificity of the corresponding rules in the base CSS. Try copying a relevant base CSS selectors exactly, even if parts of the selector seem unnecessary. While this example was being put together, liberal use was initially made of the CSS <code>!important</code> qualifier and removed later on. Also, as a probe to see if changes were taking effect, text was temporarily set to an odd <span lang="en-US"><code>color</code></span>, or borders were enabled with distinctive odd properties. This latter basic technique can be a used if advanced tools are not available. |
|||
=== Using CSS @media === |
|||
The <code>@media screen</code> qualifier over the given block is used in this case to restrict any preference change to only apply to the display of the Firebrick’s web pages on a screen and here the customisations do not apply when a page is printed. On the other hand, the <code>@media print</code> qualifier is often used to customise presentation when pages are printed, such as: getting rid of all colour, using serif fonts, changing the appearance of external links to show the actual URI, or simplifying content and hiding all unwanted or irrelevant material such as navigation lists, footers, branding. |
|||
=== Using CSS @import === |
|||
Completely separate 'print'- and 'screen' stylesheets can be maintained in separate .css files and these files can be conditionally included by reference in a master .css file using the CSS <code>@import</code> directive at the top of the file with a media-type qualifier within the directive e.g. <code>@import 'my_fb_print.css' print;</code>. This qualified import form is concise compared with using a <code>{ }</code> statement block qualifier and in theory might minimise the size of an initial CSS download, depending on the browser. A general disadvantage of <code>@import</code> is the latency introduced by additional http requests, some of which can not be parallelised, so this delay increases page rendering time, unless of course the CSS is already cached. |
|||
=== Pulling in multiple .css files === |
|||
Using the CSS <code>@import</code> directive allows multiple .css files to be pulled in general, with or without media-type qualifiers. This gets around the restriction of only being allowed to fetch a single .css file if only more than one URI value is not permitted in the single <code>css-url</code> attribute. |
|||
== Testing - warning == |
|||
There is a danger of making the Firebrick’s web UI completely unusable with mistakes in your custom CSS. To avoid this possibility, if you are using the Firebrick’s XML config editor page, use the “Test” button rather than “Save” after making your edit, as this will set a timer and will then roll back your change when the timer expires if you have not chosen “Save” before then, so you will be automatically rescued by the timeout if you are stuck. |
|||
* In order to be prepared for recovery from a bad modification, first download a good reference copy of the XML config file in advance, and then use an http upload tool - such as <code>curl</code> in Unix-like environments - to upload the good saved config file to the Firebrick. See the Firebrick manual for details on [http://www.firebrick.co.uk/fb6000/xml.php config uploading by http]. |
|||
* Many web browsers have options that allow a webpage’s CSS to be overridden, customised or ignored. |
|||
* Alternatively, depending on your chosen configuration options, you may be able to log in to the Firebrick’s command line even if you find the web UI unusable. |
|||
== Performance degradation with external websites == |
|||
If your custom CSS is located on an external web server, try to ensure that the web server of your choice is well-configured and has excellent availability in order to avoid the possibility of introducing unpleasant delays in the responsiveness of the Firebrick's web UI. (Perhaps consider testing what effect unavailability has on the behaviour of your Firebrick's UI - your Firebrick firmware release could exhibit a delay in response before a timeout if the link to the web server is broken, and as regards visual appearance if the custom CSS can not be fetched, then it could use previously cached CSS or defaults.) |
|||
If you are the web master of your chosen server, review the web server’s cache-friendliness settings. (Topics: 'cacheability', 'cache-control', 'ETags'.) Getting cacheability settings wrong could in theory at least mean that your Firebrick might possibly be compelled to refetch the custom CSS repeatedly. A number of excellent web-based tools are available to check and diagnose cacheability issues of a website. If you are using the Apache web server, see the <code>https.conf</code> or <code>.htaccess</code> documentation relating to cache control options. Make sure that user agents are not forbidden from caching downloaded CSS files, and set long cache validity times for all CSS files. Using inappropriate short cache lifetimes, even zero, or disabling caching altogether is a fairly common and heinous practice. Cache validity times should be set specifically according to each kind of file extension (<code>.css</code>) and MIME type requested (<code>text/css</code>), and should be as long as possible. The maximum validity time value is the maximum delay you feel is acceptable before a Firebrick shows the effects of a change when you change the css file on the web server. |
|||
== Security implications == |
|||
Pointing your Firebrick to a .css file that is stored in a website on the public Internet might, in theory at least, have security implications. Certainly review security of that site in general, who might have access to the site's content, FTP passwords, 'locking' features on FTP. Also consider attacks on the DNS to redirect requests to a bogus site. Man-in-the-middle attacks and ARP / ND attacks could achieve redirection at a lower level, however this is a much more general problem. Consider using TLS / SSL and use an <code>https:</code> URL to reference your .css file in order to prevent these possibilities, or use the <code>data:</code> URI scheme technique described below. |
|||
The extent of the potential outcomes that an attacker could achieve by succeeding in pulling in an evil .css file is an open question. Some versions of Microsoft Internet Explorer for Windows could cause code to be executed when ''triggered from within a mere .css file'' by the use of the powerful non standard <span lang="en-US"><code>behavior:</code></span> and <code>expression()</code> CSS features. See MSDN articles on <span lang="en-US">[https://msdn.microsoft.com/en-us/library/ms530723(v=vs.85).aspx CSS 'behavior:']</span> and [https://blogs.msdn.microsoft.com/ie/2008/10/16/ending-expressions/ CSS 'expression()']. |
|||
== Internal inline CSS - using data URIs == |
== Internal inline CSS - using data URIs == |
||
⚫ | |||
It is recommended that you should not attempt to include newlines in the inline CSS of your data URI, as this may be forbidden by the URI scheme standard. Be aware of the risk of your inline CSS containing characters that are either prohibited in data URIs, illegal in quoted strings or in XML attributes. See both the RFC for the data URI scheme and also the XML standards. Just some examples of illegal characters are ", %, &, >, newlines and various others, The simple technique of including literal CSS straight, as below, is only usable if the particular fragment of CSS does not contain any problematic characters, otherwise see the next section for a general method. |
|||
Make sure that your text editor is set to output Unicode as UTF-8 as UTF-8 encoding is expected by the data URI example below. (Specifically, if you are using Microsoft Windows, do not use Microsoft Windows 1252 ‘ANSI/Latin 1’ or other IBM/Microsoft ‘code pages’ for text representation in editors.) If you do not follow this, all non-ASCII characters will not be represented correctly in your CSS, creating bugs. Examples of non-ASCII characters include: à é ü £ … “ ” ‘ ’ × ÷ ≡ ² ː Ω ∅ and vastly many more. |
|||
Example: straight, inline CSS. Exercise caution regarding prohibited characters if adapting. In the following example, any line-breaks which be included for readability must be removed and the whole string must be entered as a single line. |
|||
⚫ | |||
<syntaxhighlight lang=xml><http css-url="data:text/css,@media screen{div.main,div.sidemenu div.menu a{font-size:x-small}}" /> |
<syntaxhighlight lang=xml><http css-url="data:text/css,@media screen{div.main,div.sidemenu div.menu a,div.topmenu,textarea{font-size:x-small}div.footer{padding:2px 10px 1px}div.footer *{vertical-align:top}}" /> |
||
</syntaxhighlight> |
</syntaxhighlight> |
||
Note the presence of the comma after <code>text/css</code>. This is essential in a <code>data</data> URI. |
|||
=== Base64-encoded data === |
=== Base64-encoded data === |
||
You may use base64-encoded data |
You may use base64-encoded <code>data</code> URIs for safety and complete flexibility as shown in the example below. Using base64-encoding removes any risks and problems with illegal characters completely. Note again the presence of the comma, now after the keyword '<code>data</code>'. This is essential in a data URI, whether base64 is used or not. |
||
If you are using any non-ASCII characters in your CSS, you should |
If you are using any non-ASCII characters in your CSS text, unless you have already CSS backslash-hex-encoded them, which avoids the issue, your CSS should be Unicode text and you must first UTF-8-encode your CSS into a byte stream, before then base64-encoding those bytes. You ''must'' then also declare that your original CSS text was UTF-8 as in the example below. |
||
In the following example, line-breaks may be included for readability. These ''must'' be removed and the whole string must be entered as a single line. |
|||
⚫ | |||
XYubWFpbixkaXYuc2lkZW1lbnUgZGl2Lm1lbnUgYXtmb250LXNpemU6eC1zbWFsbH19" |
|||
<syntaxhighlight> |
|||
⚫ | |||
bnUgZGl2Lm1lbnUgYSxkaXYudG9wbWVudSx0ZXh0YXJlYXtmb250LXNpemU6eC1zbWFsbH1kaXYuZm9vdGVye3 |
|||
BhZGRpbmc6MnB4IDEwcHggMXB4fWRpdi5mb290ZXIgKnt2ZXJ0aWNhbC1hbGlnbjp0b3B9fQ==" |
|||
</syntaxhighlight> |
</syntaxhighlight> |
||
If you are absolutely certain that your CSS will contain only ASCII characters (i.e. those below code-point 128), then the <code>;charset=UTF-8</code> declaration can be omitted. |
|||
[[Category:FireBrick|Custom]] |
[[Category:FireBrick|Custom]] |
Revision as of 14:28, 5 December 2020
Specifying custom CSS in the XML config file
You can use custom CSS to override that used by the FireBrick’s own admin webpages to customise or enhance the UI to suit your particular needs or create your own look. A user's CSS override file is specified by a URI in the XML config in an attribute on the <http>
element:
<http css-url="https://example.com/css/myfb.css">
Successfully implementing your own CSS customisations will involve studying the existing base CSS and XHTML files in your Firebrick. Be aware that because of CSS rules concerning specificity (see below) your own settings may sometimes not take precedence over the values given in the base CSS. To address this you will have to write rules that fit in with the existing structure of both the various CSS and XHTML files and add or successfully override property assignments. The latter is achieved by taking a close look at particular CSS selectors that are used in the base .css files. Detailed tips are given in later sections.
Example - changing colours
For example, to change the header and footer bar from red to blue, create your myfb.css file as:
/*
Custom css to make my FireBrick visibly different to normal ones
*/
div.header {
background: inherit;
background-color: #000080;
background: -moz-linear-gradient( top, #000080 0px, #202080 100% );
background: -webkit-gradient( linear, top, bottom, color-stop( 0%, #000080 ), color-stop( 100%, #202080 ) );
background: -webkit-linear-gradient( top, #000080 0%, #202080 100% );
background: -o-linear-gradient( top, #000080 0%, #202080 100% );
background: -ms-linear-gradient( top, #000080 0%, #202080 100% );
background: linear-gradient( top, #000080 0%, #202080 100% );
-ms-filter: "progid:DXImageTransform.Microsoft.gradient( startColorstr = '#000080', endColorstr = '#202080' )";
}
div.footer {
background: inherit;
background-color: #000080;
background: -moz-linear-gradient( top, #000080 0px, #202080 100% );
background: -webkit-gradient( linear, left top, left bottom, color-stop( 0%, #000080 ), color-stop( 100%, #202080 ) );
background: -webkit-linear-gradient( top, #000080 0%, #202080 100% );
background: -o-linear-gradient( top, #000080 0%, #202080 100% );
background: -ms-linear-gradient( top, #000080 0%, #202080 100% );
background: linear-gradient( top, #000080 0%, #202080 100% );
-ms-filter: "progid:DXImageTransform.Microsoft.gradient( startColorstr = '#000080', endColorstr = '#202080' )";
}
Image of the resulting header, showing colour change:
Example - changing font size
The following example fragment of CSS greatly reduces the font sizes in use in the Firebrick's web pages:
@media screen
{
div.main, div.sidemenu div.menu a, div.topmenu, textarea
{
font-size: x-small
}
div.footer
{
padding: 2px 10px 1px
}
div.footer *
{
vertical-align: top
}
}
Note that there is no space after the dot in div.main
etc. This is essential; adding white space at this point would alter the meaning - see CSS selectors.
Note: The above brief example is known to currently produce certain defects in the webpages’ layout: A known minor issue is that the vertical layout of the objects within the footer is slightly off.
At the time of writing, the shipping CSS in the Firebrick FB2500 was v1.45.001 Ximenes, and the standard font-size:
value in use was keyword small
. This could possibly change in future.
To increase the text size, this example would require a rewrite and lots of testing trial and error. Unfortunately changing text sizes can have a lot of nasty knock-on effects on layout, which cascade out of control in ways that are hard to predict. Hacks such as the above are likely to fall apart if the base CSS changes or if other aspects of the design cause the layout to change. This is in part because this is an override on parts of the base CSS, effectively a patch, and the user CSS has intimate dependencies on the precise base CSS content. Also there are dependencies between the (X)HTML and the CSS, so changes to the pages’ content or structure can possibly cause problems.
CSS debugging tips
There are many powerful tools available for debugging CSS. When developing an override such as this, problems with the CSS specificity rules may mean that your property overrides do not take effect, as they do not ‘win’ over the specificity of the corresponding rules in the base CSS. Try copying a relevant base CSS selectors exactly, even if parts of the selector seem unnecessary. While this example was being put together, liberal use was initially made of the CSS !important
qualifier and removed later on. Also, as a probe to see if changes were taking effect, text was temporarily set to an odd color
, or borders were enabled with distinctive odd properties. This latter basic technique can be a used if advanced tools are not available.
Using CSS @media
The @media screen
qualifier over the given block is used in this case to restrict any preference change to only apply to the display of the Firebrick’s web pages on a screen and here the customisations do not apply when a page is printed. On the other hand, the @media print
qualifier is often used to customise presentation when pages are printed, such as: getting rid of all colour, using serif fonts, changing the appearance of external links to show the actual URI, or simplifying content and hiding all unwanted or irrelevant material such as navigation lists, footers, branding.
Using CSS @import
Completely separate 'print'- and 'screen' stylesheets can be maintained in separate .css files and these files can be conditionally included by reference in a master .css file using the CSS @import
directive at the top of the file with a media-type qualifier within the directive e.g. @import 'my_fb_print.css' print;
. This qualified import form is concise compared with using a { }
statement block qualifier and in theory might minimise the size of an initial CSS download, depending on the browser. A general disadvantage of @import
is the latency introduced by additional http requests, some of which can not be parallelised, so this delay increases page rendering time, unless of course the CSS is already cached.
Pulling in multiple .css files
Using the CSS @import
directive allows multiple .css files to be pulled in general, with or without media-type qualifiers. This gets around the restriction of only being allowed to fetch a single .css file if only more than one URI value is not permitted in the single css-url
attribute.
Testing - warning
There is a danger of making the Firebrick’s web UI completely unusable with mistakes in your custom CSS. To avoid this possibility, if you are using the Firebrick’s XML config editor page, use the “Test” button rather than “Save” after making your edit, as this will set a timer and will then roll back your change when the timer expires if you have not chosen “Save” before then, so you will be automatically rescued by the timeout if you are stuck.
- In order to be prepared for recovery from a bad modification, first download a good reference copy of the XML config file in advance, and then use an http upload tool - such as
curl
in Unix-like environments - to upload the good saved config file to the Firebrick. See the Firebrick manual for details on config uploading by http.
- Many web browsers have options that allow a webpage’s CSS to be overridden, customised or ignored.
- Alternatively, depending on your chosen configuration options, you may be able to log in to the Firebrick’s command line even if you find the web UI unusable.
Performance degradation with external websites
If your custom CSS is located on an external web server, try to ensure that the web server of your choice is well-configured and has excellent availability in order to avoid the possibility of introducing unpleasant delays in the responsiveness of the Firebrick's web UI. (Perhaps consider testing what effect unavailability has on the behaviour of your Firebrick's UI - your Firebrick firmware release could exhibit a delay in response before a timeout if the link to the web server is broken, and as regards visual appearance if the custom CSS can not be fetched, then it could use previously cached CSS or defaults.)
If you are the web master of your chosen server, review the web server’s cache-friendliness settings. (Topics: 'cacheability', 'cache-control', 'ETags'.) Getting cacheability settings wrong could in theory at least mean that your Firebrick might possibly be compelled to refetch the custom CSS repeatedly. A number of excellent web-based tools are available to check and diagnose cacheability issues of a website. If you are using the Apache web server, see the https.conf
or .htaccess
documentation relating to cache control options. Make sure that user agents are not forbidden from caching downloaded CSS files, and set long cache validity times for all CSS files. Using inappropriate short cache lifetimes, even zero, or disabling caching altogether is a fairly common and heinous practice. Cache validity times should be set specifically according to each kind of file extension (.css
) and MIME type requested (text/css
), and should be as long as possible. The maximum validity time value is the maximum delay you feel is acceptable before a Firebrick shows the effects of a change when you change the css file on the web server.
Security implications
Pointing your Firebrick to a .css file that is stored in a website on the public Internet might, in theory at least, have security implications. Certainly review security of that site in general, who might have access to the site's content, FTP passwords, 'locking' features on FTP. Also consider attacks on the DNS to redirect requests to a bogus site. Man-in-the-middle attacks and ARP / ND attacks could achieve redirection at a lower level, however this is a much more general problem. Consider using TLS / SSL and use an https:
URL to reference your .css file in order to prevent these possibilities, or use the data:
URI scheme technique described below.
The extent of the potential outcomes that an attacker could achieve by succeeding in pulling in an evil .css file is an open question. Some versions of Microsoft Internet Explorer for Windows could cause code to be executed when triggered from within a mere .css file by the use of the powerful non standard behavior:
and expression()
CSS features. See MSDN articles on CSS 'behavior:' and CSS 'expression()'.
Internal inline CSS - using data URIs
To avoid having to use an external website to store your custom CSS, you can employ a data:
URI - see RFC 2397. Be aware that there may be a limit on the length of URIs however, and in any event see RFC 2397 section 2.
It is recommended that you should not attempt to include newlines in the inline CSS of your data URI, as this may be forbidden by the URI scheme standard. Be aware of the risk of your inline CSS containing characters that are either prohibited in data URIs, illegal in quoted strings or in XML attributes. See both the RFC for the data URI scheme and also the XML standards. Just some examples of illegal characters are ", %, &, >, newlines and various others, The simple technique of including literal CSS straight, as below, is only usable if the particular fragment of CSS does not contain any problematic characters, otherwise see the next section for a general method.
Make sure that your text editor is set to output Unicode as UTF-8 as UTF-8 encoding is expected by the data URI example below. (Specifically, if you are using Microsoft Windows, do not use Microsoft Windows 1252 ‘ANSI/Latin 1’ or other IBM/Microsoft ‘code pages’ for text representation in editors.) If you do not follow this, all non-ASCII characters will not be represented correctly in your CSS, creating bugs. Examples of non-ASCII characters include: à é ü £ … “ ” ‘ ’ × ÷ ≡ ² ː Ω ∅ and vastly many more.
Example: straight, inline CSS. Exercise caution regarding prohibited characters if adapting. In the following example, any line-breaks which be included for readability must be removed and the whole string must be entered as a single line.
<http css-url="data:text/css,@media screen{div.main,div.sidemenu div.menu a,div.topmenu,textarea{font-size:x-small}div.footer{padding:2px 10px 1px}div.footer *{vertical-align:top}}" />
Note the presence of the comma after text/css
. This is essential in a data URI.
Base64-encoded data
You may use base64-encoded data
URIs for safety and complete flexibility as shown in the example below. Using base64-encoding removes any risks and problems with illegal characters completely. Note again the presence of the comma, now after the keyword 'data
'. This is essential in a data URI, whether base64 is used or not.
If you are using any non-ASCII characters in your CSS text, unless you have already CSS backslash-hex-encoded them, which avoids the issue, your CSS should be Unicode text and you must first UTF-8-encode your CSS into a byte stream, before then base64-encoding those bytes. You must then also declare that your original CSS text was UTF-8 as in the example below.
In the following example, line-breaks may be included for readability. These must be removed and the whole string must be entered as a single line.
css-url="data:text/css;charset=UTF-8;base64,QG1lZGlhIHNjcmVlbntkaXYubWFpbixkaXYuc2lkZW1l
bnUgZGl2Lm1lbnUgYSxkaXYudG9wbWVudSx0ZXh0YXJlYXtmb250LXNpemU6eC1zbWFsbH1kaXYuZm9vdGVye3
BhZGRpbmc6MnB4IDEwcHggMXB4fWRpdi5mb290ZXIgKnt2ZXJ0aWNhbC1hbGlnbjp0b3B9fQ=="
If you are absolutely certain that your CSS will contain only ASCII characters (i.e. those below code-point 128), then the ;charset=UTF-8
declaration can be omitted.