PDA

View Full Version : CSS Variables?


RSLancastr
26th October 2006, 12:10 PM
Is there any way to use variables within CSS?

For example: I am creating a style sheet which includes various colors (background colors, font colors, etc).

Every time I experiment with different colors, I have to do a scan/replace to change all the references to a given color. This becomes even more of a pain in the ass if I have used the same color for more than one element, but want to change only one of them.

It would be nice if I could just define variables (like MainBackgroundColor, etc) up front and use those variables throughout the sheet, so I only have to change the statement where the variable's value is set.

Is there any such capability within CSS?

RSLancastr
26th October 2006, 12:24 PM
(I have already asked a Mod to correct the "CASS" in the thread title.)

Terry
26th October 2006, 12:29 PM
You just can't stop thinking about Kaz, can you? ;)

RSLancastr
26th October 2006, 12:55 PM
Grrrr...

Demigorgon
26th October 2006, 02:13 PM
No.

Well, sort of... (http://www.chrisjdavis.org/2005/10/16/php-in-css/)

RSLancastr
26th October 2006, 02:28 PM
No.

Well, sort of... (http://www.chrisjdavis.org/2005/10/16/php-in-css/)Thanks, I will look into that.

(At first I didn't notice it was a link. This new forum look is confusing...)

DangerousBeliefs
27th October 2006, 11:08 AM
How are you building your objects?

You shouldn't have a whole lot of objects to change. You aren't using one of those cursied WYSIWYG editors, are you?

(Also, have you tried find/replace? :D )

RSLancastr
27th October 2006, 03:19 PM
How are you building your objects?If by "objects" you mean the .css and .htm files, I am using a text editor.

(Also, have you tried find/replace? :D )Yes, but again, if you are using the same color for more than one purpose, using find/replace to change its use for ONE of those purposes without changing it for the others becomes problematic.

I've found a workaround which helps with my particular situation. The majority of colors I am dealing with are background colors, so I am using little one-color .jpg files for the background colors. Although this can make for some delays while the image is loaded, all I have to do to change the color throughout the site is to change the .jpg.

I may go back to #xxxxxx literals later, but for now, while I am experimenting with various combinations, it is helpful.

DangerousBeliefs
27th October 2006, 04:46 PM
If by "objects" you mean the .css and .htm files, I am using a text editor.


No. The purpose of .css is to describe objects in the HTML.

You should have to change ONE color in the .css to change all background color on all pages.

Do you have an example of the HTML/CSS online to look at?

RSLancastr
27th October 2006, 05:34 PM
No. The purpose of .css is to describe objects in the HTML.Ah. I didn't think of the divs and such as objects.

How am I building them? With a text editor.

You should have to change ONE color in the .css to change all background color on all pages.Yes. But if you have multiple objects (within a given css) which refer to this same color, you have to change it on ALL objects. It would be nicer if it could be done in one spot in the css rather than several.

It still beats hell out of changing it in every html on the site, though.

I don't currently have any of it up on a server, but will by the end of the month.

kevin
28th October 2006, 10:28 AM
only if the style information is generated dynamically.

A good text editor (or even a css specific editor) can help you at least find and replace them much more quickly. PSPad is free and pretty good:
http://www.pspad.com/en/

Using CSS inheritance properly can sometimes reduce the need for specifying things over and over, although without seeing the CSS directly I can't say that for sure.

I've seen a lot of problems with people just specifying TOO many classes, not ever block of text needs to be classified differently from everything else.

logical muse
31st October 2006, 09:25 PM
Hey RSL...

Are you a C programmer?

If so, this will (potentially) make sense. Use the C preprocessor.

RSLancastr
31st October 2006, 09:39 PM
Hey RSL...

Are you a C programmer?

If so, this will (potentially) make sense. Use the C preprocessor.Sorry, although I did write a program or two in C long ago and far away, I am by no stretch of the imagination a C programmer.

logical muse
31st October 2006, 10:27 PM
Sorry, although I did write a program or two in C long ago and far away, I am by no stretch of the imagination a C programmer.

That's OK, my solution for you doesn't require you to know C, but it uses the macro facility of the C preprocessor.

This is easy, btw... Here's how:

I'll use a simple example css file (test.css) with only four lines in it:


a:link {color:#2f78c0;}
a:visited {color:#2f78c0;}
a:hover {color:#2fc0c0;}
a:active {color:#2fc0c0;}


Notice how in this contrived example, we want to use the same colour a couple of times. In fact, we want to do this for a couple of colours.

OK, rename the file to test.cssp (or something).

Modify it as so:


#define LINK_COLOUR 2f78c0
#define HOVER_COLOUR 2fc0c0

a:link {color:#LINK_COLOUR;}
a:visited {color:#LINK_COLOUR;}
a:hover {color:#HOVER_COLOUR;}
a:active {color:#HOVER_COLOUR;}


See what we've done? We've defined macros that the C preprocessor will expand.

Use this command line:

gcc -E -x c -P test.cssp > test.css

This will expand the macros and create a file called test.css for you, with your colour values inserted in the right place.

Let me know if you need more info.

logical muse
1st November 2006, 01:24 AM
I've looked into this further, and it might be more useful to use the m4, or gm4, macro processor program instead of the C preprocessor.

Google 'css preprocessor' or 'html preprocessor' and you'll find lots of information.

Wudang
1st November 2006, 04:13 AM
Try http://www.barelyfitz.com/projects/csscolor/

logical muse
2nd November 2006, 03:27 AM
I'd like to give an example of how to do this using the m4 macro processor, rather than the C preprocessor. The example is for a CSS fixed-width three-column layout, and demonstrates the flexibility of the macro processor approach.

Say you want a layout that's 768 pixels wide, divided into three columns, 164, 448, and 156 pixels wide respectively. There's padding applied to each column, and you have a hack in there to make sure it works in (nearly) all browsers. To get some of the values you need, you have to apply a little arithmetic to the column and padding widths.

If you ever wanted to change the widths, you'd have to recalculate everything. We'll use m4 to do all the hard work for us, and make it very easy to make new layouts with different widths.

Please note that this approach can be used for any layout type, not just the one presented here.

OK, time to look at some code. The CSS we want to end up with is this:


* { margin: 0; padding : 0; }
#wrapper { width: 768px; }
#col_container { width: 448px; padding-left: 164px; padding-right: 156px; }
#col_container .column { position: relative; float: left; }
* html #col_left { width: 164px; w\idth: 148px; }
#col_left { width: 148px; margin-left: -612px; padding: 0px 8px 0px 8px; }
* html #col_middle { width: 448px; w\idth: 416px; }
#col_middle { width: 416px; padding: 0px 16px 0px 16px; }
* html #col_right { width: 156px; w\idth: 140px; }
#col_right { width: 140px; margin-right: -156px; padding: 0px 8px 0px 8px; }
#footer { clear: both; }


I won't go into details about how all the values were arrived at. You'll see the calculations in the next bit of code.

Normally, you'd create a .css file and put all that code in there. What we're going to do, though, is create a .m4 file (actually, the extension is irrelevant) and use the m4 program to generate our .css file.

Here's the .m4 file:


changecom(`~')

define(`LINK_COLOUR', 2f78c0)
define(`HOVER_COLOUR', 2fc0c0)

define(`COL_LEFT_FULL_WIDTH', 164)
define(`COL_LEFT_LEFT_PAD', 8)
define(`COL_LEFT_RIGHT_PAD', 8)
define(`COL_LEFT_WIDTH', eval(COL_LEFT_FULL_WIDTH - COL_LEFT_LEFT_PAD - COL_LEFT_RIGHT_PAD))

define(`COL_MIDDLE_FULL_WIDTH', 448)
define(`COL_MIDDLE_LEFT_PAD', 16)
define(`COL_MIDDLE_RIGHT_PAD', 16)
define(`COL_MIDDLE_WIDTH', eval(COL_MIDDLE_FULL_WIDTH - COL_MIDDLE_LEFT_PAD - COL_MIDDLE_RIGHT_PAD))

define(`COL_RIGHT_FULL_WIDTH', 156)
define(`COL_RIGHT_LEFT_PAD', 8)
define(`COL_RIGHT_RIGHT_PAD', 8)
define(`COL_RIGHT_WIDTH', eval(COL_RIGHT_FULL_WIDTH - COL_RIGHT_LEFT_PAD - COL_RIGHT_RIGHT_PAD))

define(`FULL_WIDTH', eval(COL_LEFT_FULL_WIDTH + COL_MIDDLE_FULL_WIDTH + COL_RIGHT_FULL_WIDTH))

a:link {color:#LINK_COLOUR;}
a:visited {color:#LINK_COLOUR;}
a:hover {color:#HOVER_COLOUR;}
a:active {color:#HOVER_COLOUR;}

* { margin: 0; padding : 0; }
#wrapper { width: FULL_WIDTH()px; }
#col_container { width: COL_MIDDLE_FULL_WIDTH()px; padding-left: COL_LEFT_FULL_WIDTH()px; padding-right: COL_RIGHT_FULL_WIDTH()px; }
#col_container .column { position: relative; float: left; }
* html #col_left { width: COL_LEFT_FULL_WIDTH()px; w\idth: COL_LEFT_WIDTH()px; }
#col_left { width: COL_LEFT_WIDTH()px; margin-left: -eval(COL_MIDDLE_FULL_WIDTH + COL_LEFT_FULL_WIDTH)px; padding: 0px COL_LEFT_RIGHT_PAD()px 0px COL_LEFT_LEFT_PAD()px; }
* html #col_middle { width: COL_MIDDLE_FULL_WIDTH()px; w\idth: COL_MIDDLE_WIDTH()px; }
#col_middle { width: COL_MIDDLE_WIDTH()px; padding: 0px COL_MIDDLE_RIGHT_PAD()px 0px COL_MIDDLE_LEFT_PAD()px; }
* html #col_right { width: COL_RIGHT_FULL_WIDTH()px; w\idth: COL_RIGHT_WIDTH()px; }
#col_right { width: COL_RIGHT_WIDTH()px; margin-right: -COL_RIGHT_FULL_WIDTH()px; padding: 0px COL_RIGHT_RIGHT_PAD()px 0px COL_RIGHT_LEFT_PAD()px; }
#footer { clear: both; }


It contains a couple of other things in there as well as the layout.

If we run this command line:

m4 test.m4 > test.css

(assuming that the file was called test.m4) then the m4 program will generate a file called test.css with the following content:


a:link {color:#2f78c0;}
a:visited {color:#2f78c0;}
a:hover {color:#2fc0c0;}
a:active {color:#2fc0c0;}

* { margin: 0; padding : 0; }
#wrapper { width: 768px; }
#col_container { width: 448px; padding-left: 164px; padding-right: 156px; }
#col_container .column { position: relative; float: left; }
* html #col_left { width: 164px; w\idth: 148px; }
#col_left { width: 148px; margin-left: -612px; padding: 0px 8px 0px 8px; }
* html #col_middle { width: 448px; w\idth: 416px; }
#col_middle { width: 416px; padding: 0px 16px 0px 16px; }
* html #col_right { width: 156px; w\idth: 140px; }
#col_right { width: 140px; margin-right: -156px; padding: 0px 8px 0px 8px; }
#footer { clear: both; }


How's that? Exactly what we were after.

If you study our .m4 file, you'll see definitions for column widths and paddings. You can simply change any of them and all the dependent values will be calculated automatically, saving you a lot of work and error-proofing your code.

I prefer this to the php approach for a number of reasons:


It doesn't rely on a web server, meaning I can experiment with my css on my, or any, local machine.
The generated CSS file is just like any other CSS file, and will be cached by browsers, saving a hit on every page on your site. The PHP version won't be cached in browsers.
It doesn't require the PHP interpreter to run on each hit, saving time and resources.
PHP is really for dynamic content. Preprocessing is for static content.


Now, let's take a look at our .m4 file in detail.

The first line:
changecom(`~')
changes m4's comment delimiter from the default '#' to '~'. Otherwise, text coming after '#' would be seen as comments.

define(`COL_LEFT_FULL_WIDTH', 164)
defines a macro called COL_LEFT_FULL_WIDTH and sets its expansion to 164. Simple stuff, really.

define(`COL_LEFT_WIDTH', eval(COL_LEFT_FULL_WIDTH - COL_LEFT_LEFT_PAD - COL_LEFT_RIGHT_PAD))
defines a macro called COL_LEFT_WIDTH and sets it to the result of the operation evaluated by the eval builtin macro.

a:link {color:#LINK_COLOUR;}
calls the macro LINK_COLOUR, replacing the text LINK_COLOUR with the text 2f78c0.

#wrapper { width: FULL_WIDTH()px; }
The macro call here has braces after it, otherwise we'd have FULL_WIDTHpx as our token and the macro processor would not recognise the macro.

#col_left { width: COL_LEFT_WIDTH()px; margin-left: -eval(COL_MIDDLE_FULL_WIDTH + COL_LEFT_FULL_WIDTH)px; padding: 0px COL_LEFT_RIGHT_PAD()px 0px COL_LEFT_LEFT_PAD()px; }
This line has a number of macro expansions, including an eval macro call for some arithmetic.

You can compare the .m4 file to the generated .css file to see how the macros are expanded.

The m4 program is available as standard on Unix computers, including Linux and Mac. It's also available for Windows (http://gnuwin32.sourceforge.net/packages.html).

RSLancastr
3rd November 2006, 01:43 PM
Thanks LM for the wonderful examples. I'm not sure if this is the route I'll be taking, but I definitely appreciate your help.

logical muse
3rd November 2006, 08:15 PM
Thanks LM for the wonderful examples. I'm not sure if this is the route I'll be taking, but I definitely appreciate your help.
No worries. It might be of use to someone out there.

skoob
4th November 2006, 01:18 AM
Instead of using variables, you could simply specify common properties (such as colours) for multiple elements in one statement:

.menu, .footer, .content .list {
color: #FF00FF;
font-family: "Comic Sans";
}You can then add specific properties (that aren't the same in a of the specified elements) in separate CSS statements.

kevin
4th November 2006, 09:02 PM
That's OK, my solution for you doesn't require you to know C, but it uses the macro facility of the C preprocessor.

This is easy, btw... Here's how:

I'll use a simple example css file (test.css) with only four lines in it:


a:link {color:#2f78c0;}
a:visited {color:#2f78c0;}
a:hover {color:#2fc0c0;}
a:active {color:#2fc0c0;}


Notice how in this contrived example, we want to use the same colour a couple of times. In fact, we want to do this for a couple of colours.

OK, rename the file to test.cssp (or something).

Modify it as so:


#define LINK_COLOUR 2f78c0
#define HOVER_COLOUR 2fc0c0

a:link {color:#LINK_COLOUR;}
a:visited {color:#LINK_COLOUR;}
a:hover {color:#HOVER_COLOUR;}
a:active {color:#HOVER_COLOUR;}


See what we've done? We've defined macros that the C preprocessor will expand.

Use this command line:

gcc -E -x c -P test.cssp > test.css

This will expand the macros and create a file called test.css for you, with your colour values inserted in the right place.

Let me know if you need more info.

I really think you're using a sledgehammer to fix a problem.

Although your example is simplified in CSS you can group multiple items together:

a:link, a:visted {color:#2f78c0;}
a:hover, a:active {color:#2fc0c0;}

there, each color used once. same effect, except to test your site you don't need to run a make step.

logical muse
5th November 2006, 04:01 AM
I really think you're using a sledgehammer to fix a problem.

Although your example is simplified in CSS you can group multiple items together:

a:link, a:visted {color:#2f78c0;}
a:hover, a:active {color:#2fc0c0;}

there, each color used once. same effect, except to test your site you don't need to run a make step.
It was a simplified example, as you rightly point out. Don't underestimate the technique's power though. I kept the example as simple as possible to demonstrate the technique.

It really comes into its own when values need to be calculated. You can't solve that problem by groupling multiple items together.

Have a look at the m4 example I gave in this message (http://forums.randi.org/showthread.php?postid=2062101#post2062101).

kevin
5th November 2006, 04:07 PM
No doubt it's a flexible method, but as I said I dislike web solutions that require a separate make step. They make testing harder.

Additionally for your other example, how frequently do you need calculated values in CSS? You use column widths as an example, but if you're changing columns widths so frequently that calculating them yourself takes too long then there is something wrong with your website. Not to mention I hate fixed width sites period. They don't render properly when I'm using a small virtual connection to browse (many support sites suck in these scenarios) or they waste tons of space when I'm browsing on my big monitors at work.

I would see value in something like this for a consultant that was making modifications to a standard CSS file to would provide customized solutions for many different customers. For one person maintaining a website, wrong solution. IMO of course.

logical muse
5th November 2006, 05:31 PM
No doubt it's a flexible method, but as I said I dislike web solutions that require a separate make step. They make testing harder.

Thanks for your comments. Yes, it is flexible. I don't agree that it makes testing harder. If anything, it can reduce the potential for errors.

Additionally for your other example, how frequently do you need calculated values in CSS? You use column widths as an example, but if you're changing columns widths so frequently that calculating them yourself takes too long then there is something wrong with your website.

I didn't say that you'd be changing column widths for your web site frequently. Take a look at a typical article on CSS multi-column layouts (http://alistapart.com/articles/holygrail). Several calculations are required. The preprocessor automates the process.

Not to mention I hate fixed width sites period. They don't render properly when I'm using a small virtual connection to browse (many support sites suck in these scenarios) or they waste tons of space when I'm browsing on my big monitors at work.

Thanks for your opinion on fixed width sites, but please allow me to say that it's irrelevant to this discussion. I could have just as easily used a liquid layout, or fluid layout. The choice of a fixed width layout in my example has absolutely no bearing on the validity or usefulness of the technique. If I had used a liquid layout as an example, someone else would have made the comment that they hate web sites that expand to the full width of the window as it makes text lines too long to read easily. Let's not make this about fixed versus liquid layouts.

I would see value in something like this for a consultant that was making modifications to a standard CSS file to would provide customized solutions for many different customers. For one person maintaining a website, wrong solution. IMO of course.

With a little imagination, you can see that this can be used for HTML as well as CSS. Are there any repetitive tasks that consume your time when developing web sites? How about the navigation on each page? One of my web sites has hundreds of static pages. Two new pages are added every week, and hundreds of pages need to be modified to include links to the new pages. I don't use Dreamweaver or any other package, I develop my sites just using a text editor. Using techniques similar to those described above, adding new pages to this site takes almost no time. Literally, just seconds, and all the relevant pages are automatically regenerated with links to the new pages.

There is no doubt there is value in this method. Maybe not for you, but I've saved lots of time in development, maintenance and testing using something similar to this. My requirements may be more demanding than most, though. If it's not for you, that's fine. It may be useful to others.

Happy developing!

kevin
5th November 2006, 07:57 PM
my websites are dynamically driven html with static css. reversing that, static html with dynamic css, seems, well, backwards to me.

I'm not trying to argue you out of something you seem to think is a good idea, it's just a solution i wouldn't implement.

logical muse
5th November 2006, 09:41 PM
my websites are dynamically driven html with static css. reversing that, static html with dynamic css, seems, well, backwards to me.

I'm not trying to argue you out of something you seem to think is a good idea, it's just a solution i wouldn't implement.

Fair enough, but you're misrepresenting the technique.

None of my web sites are static html with dynamic css. That's completely missing the point.

Some of my web sites are dynamic driven html with static css, just as yours are.

Some of my web sites are static html and static css.

In fact, using a preprocessor makes sense for static sites, as I mentioned in one of my posts above. Someone else was proposing PHP for CSS variables, which didn't make sense to me.

PHP is for dynamic sites, preprocessing is for static sites (or files), as I've already mentioned.

I use this technique for my sites to great effect. Not for CSS, for HTML.

Here's a question for you. Let's say you have a client who wants a static html site and you code it all in a text editor, and there are, say, eight pages on the site. There's a menu on the left hand side with eight links.

The client wants a change, maybe an additional page. How long does it take you to do it? Do you have to edit each existing page's html file to add the link to the new page? And remember, the navigation code is different for each page as the current page's menu item needs to be highlighted.

The client's phone number changes. Do you know on how many pages the phone number appears? How long does it take to change them all?

Using a macro preprocessor, these changes are made in seconds. I can add a new page to a web site by adding one line to a text file and running my program. The line I add is the name of the page, something like:

about

By doing that, and only that, all the pages of the site are rebuilt, all linking to the new page, the new page is created and ready for me to add some content.

If there is some content that is used multiple times over a few pages, I create a macro for it. The content is defined in one place, and changes can be easily made.

It's a remarkably powerful system that I've developed for radidly creating and maintaining web sites, that incorporates macro expansion and templating. Just because I showed some examples of using m4 for css doesn't mean that's the only use for this kind of technology.

Mind you, I've never used Dreamweaver or Frontpage or whatever it is that web designers use, so I don't know how they handle these tasks.




eta: OK I won't say any more on this matter as I'm giving away my competitive advantage!

RSLancastr
6th November 2006, 02:08 AM
Instead of using variables, you could simply specify common properties (such as colours) for multiple elements in one statement:D'oh!!

This will solve some, though not all of my CSS-color problems.

And I knew about it, but didn't consider using it for this! :o

Thanks!