Take the 2-minute tour ×
Mathematica Stack Exchange is a question and answer site for users of Mathematica. It's 100% free, no registration required.

How can I parse a .css file generated by Mathematica, for example when exporting a notebook to HTML? What is te best way to modify or add new values to the CSS?

I've written a simple function to add some values to a .css file:

ImportTxt[file_, Elements_: "String"] :=  Module[{file1 = file, absoluteFileName,    fileNameTxt}, (fileNameTxt = ((FileNameDrop[           absoluteFileName = AbsoluteFileName[#]] <> "\\" <>           FileBaseName[#]) &@file) <> ".txt");   If[FileExistsQ[fileNameTxt], DeleteFile[fileNameTxt];    CopyFile[file, fileNameTxt]; Import[fileNameTxt, Elements],    CopyFile[file, fileNameTxt]; Import[fileNameTxt, Elements]]]

ExportCSS[file_, content_] :=  Module[{fileTxt = file <> ".txt", fileCss = file <> ".css"},   Export[fileTxt, content];   If[FileExistsQ[fileCss], DeleteFile[fileCss];    RenameFile[fileTxt, fileCss], RenameFile[fileTxt, fileCss]]]

cssAdd[cssFile_, name_, value_] :=  Module[{cssFileTxt},   If[FileExistsQ[cssFile] == False, Print["File-Not-Exists"];    Abort[]]; cssData = ImportTxt[cssFile, "Data"];   cssDataList =    Partition[SplitBy[cssData, StringMatchQ[#, "/*" ~~ __ ~~ "*/"] &],     2];  pos = Position[cssDataList, "." <> name <> " {"][[1]];  result = Insert[cssDataList, value, pos + {0, 0, 1}];  ExportCSS[cssFile // StringDrop[#, -4] &,    StringJoin@Map[Riffle[#, "\n"] &, result, {1, 2}]]]

For example:

cssAdd["index", "Text", "width:300px;"]

will add the value width:300px; to the css file, but I encounter problems if I try to do this manipulation repeatedly.

If I continue, changing the value width:300px; into width:500px;, the second value doesn't work (ie. width:300px; will override the width:500px;).

In my code: I use pos + {0, 0, 1} to get the position where the new value will be inserted, and I think this could be part of my problem.

Let me try Reverse a sublist:



In context this looks like:


This is how I think it should look:


How can this approach be improved? For example, is it better to import as "String" or "Data"?

Since PageWidth doesn't seem to take effect after exporting to HTML, I need to manually map the value of PageWidth to the width in.css file.

Update one of my solution: I find the place of "}" after ".Text {"

pos1=Position[cssDataList,"."<>name<>" {"][[1]];
share|improve this question
@cormullion hi, I think you know much about something about .css file. –  HyperGroups Dec 20 '13 at 7:27
500px will override 300px, yes, but isn't this what you want? –  Pickett Dec 20 '13 at 7:41
@Anon no, 300px override 500px, my function add a new value just after .name { –  HyperGroups Dec 20 '13 at 7:43
Hi - no I know very little about CSS, except that it cascades (inherits). But your question isn't clear - what are the different selectors for width. What is overriding what? And your 'parser' won't work on all CSS files (they can be very complex- even containing image data). I wonder why Mathematica doesn't parse CSS files? –  cormullion Dec 20 '13 at 8:42
@cormullion ah, fine, I mean the .css file generated by Mathematica Exporting notobook to HTML. –  HyperGroups Dec 20 '13 at 8:45

1 Answer 1

You've added some additional data since I started working on my solution and I now have a better understanding of your problem. You attempted to replace a value and ended up with


It's much easier to append the rule at the end of the file, so you get:



This is valid CSS, where the last rule has precedence over the former. In fact, this property of CSS is very, very commonly used. For example almost every website includes a stylesheet that gets rid of browser inconsistencies. Then usually a sort of framework with handy and common rules, and then a third stylesheet with site-specific styles. Each stylesheet overrides the former. So what you ought to do is create a stylesheet that overrides the Mathematica styles you don't like and include it after you include the Mathematica stylesheet.

However, I've written a simple example of how you can work with CSS. It should work for the most common purposes. It only has one function so far, which is to add/update a property but you can easily extend it.

Let's start with some basic CSS:

css = ".navbar-inverse .navbar-brand,
  .navbar-inverse .navbar-nav > li > a {
    text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);

  .navbar-fixed-bottom {
    border-radius: 0;

  .alert {
    text-shadow: 0 1px 0 rgba(255, 255, 255, 0.2);
    -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.25), 0 \
1px 2px rgba(0, 0, 0, 0.05);
            box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.25), 0 \
1px 2px rgba(0, 0, 0, 0.05);

  .alert-success {
    background-image: -webkit-linear-gradient(top, #dff0d8 0%, \
#c8e5bc 100%);
    background-image: linear-gradient(to bottom, #dff0d8 0%, #c8e5bc \
    background-repeat: repeat-x;
    border-color: #b2dba1;
    filter: \
progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffdff0d8', \
endColorstr='#ffc8e5bc', GradientType=0);

Here's the parser, I hope it's clear what it does from the comments. The regular expressions are very simple, one can think of them as string patterns where .*? is _.

{selectors, properties} = 
   StringCases[StringReplace[css, "\n" -> ""](* The . 
    selector does not match newlines *),
    RegularExpression["(.*?){(.*?)}"] -> {"$1", 
          "$2"} (* $1 is the content of the first parenthesis, $2 that of \
the second *)
selectors = 
  StringTrim /@ 
   StringSplit[selectors, ","]; (* Selectors are divided by comma *)

properties = 
  StringTrim /@ 
      RegularExpression["(.*?):(.*?);"] -> {"$1", "$2"}] & /@ 
   properties; (* Each property is of the form name: value; *)

rules = Transpose[{selectors, properties}];

Now execute rules // TableForm and inspect the values. To change a value I created this utility function:

propertyUpdate[rules_, selector_, name_, value_] := If[
  MatchQ[rules, {___, {{___, 
      selector, ___}, {___, {name, ___}, ___}}, ___}](* 
  The property already has a value *),
  rules /. {x___, {s : {___, selector, ___}, {a : ___, {name, ___}, 
       b : ___}}, y___} :> {x, {s, {a, {name, value}, b}}, y},
  Append[rules, {selector, {{name, value}}}]

To try it, execute this and compare with the original value:

propertyUpdate[rules, ".alert", "box-shadow", "newValue"] // TableForm
share|improve this answer
ha, thanks, I need time to digest your answer. I see one important thing is we can just add a total .Text {width:300px;} in the end of the file, that broaden the functions we could write. I've added a solution along my function, find the place of "}". –  HyperGroups Dec 20 '13 at 9:17

Your Answer


By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.