noprompt / garden

Generate CSS with Clojure
1.34k stars 87 forks source link

Property order is different in output CSS, renders incorrectly in browser #180

Closed Jarzka closed 4 years ago

Jarzka commented 4 years ago

Hi

I noticed the following problem when generating CSS from a Clojure map:

(garden.core/css [:body {:font-family "open_sans, Verdana, Helvetica, sans-serif"
                         :color "#121212"
                         :background "black url('/images/background2.jpg')"
                         :background-repeat "no-repeat"
                         :background-position "center"
                         :background-attachment "fixed"
                         :background-size "cover"
                         :margin 0
                         :padding 0}])

It generates the following CSS:

body {
    background-position: center;
    background-attachment: fixed;
    background-repeat: no-repeat;
    font-family: open_sans, Verdana, Helvetica, sans-serif;
    margin: 0;
    padding: 0;
    background-size: cover;
    background: black url('/images/background2.jpg');
    color: #121212;
}

The order of properties has changed. This sould not be a problem in most cases, but in this case it is, because it seems that browser ignores background position values if the background is not defined first.

Here is a proof of this (repeats in Firefox & Chrome) https://jsfiddle.net/75byvs96/ --> Background defined last, render incorrectly (position properties are ignored) https://jsfiddle.net/75byvs96/1/ --> Background defined first, renders correctly.

Jarzka commented 4 years ago

I solved this by using sorted-map.

harold commented 4 years ago

Interesting! Never thought about this (Clojure map keys are unordered, so this makes sense)

In this case sorted-map helps because alphabetical order happens to work. :smile:

Jarzka commented 4 years ago

Yes, in this case it works. However, if at some point I would need to define property order fully manually, this might be a bit problematic.

Jarzka commented 4 years ago

Would it be possible to define style map as a vector in that case? Or... maybe the different order of properties causing problems is so rare that there is no need to add syntax support for defining properties in a vector. One can also use sorted-map-by to solve this.

aisamu commented 4 years ago

There's also ordered-map https://github.com/clj-commons/ordered, which stores things as they're inserted.

Also note that you can use multiple maps, per https://github.com/noprompt/garden/issues/67

Jarzka commented 4 years ago

I also noticed that this is probably a problem only when using shorthands, as:

As with all shorthand properties, any omitted sub-values will be set to their initial value.

So, if I use background-color and background-image instead of background, the order does not matter.

noprompt commented 4 years ago

FYI you can also use more maps if the order of properties is relevant:

(garden.core/css
 [:body
  {:font-family "open_sans, Verdana, Helvetica, sans-serif"
   :color "#121212"}
  {:background "black url('/images/background2.jpg')"}
  {:background-repeat "no-repeat"}
  {:background-position "center"}
  {:background-attachment "fixed"}
  {:background-size "cover"}
  {:margin 0
   :padding 0}])

Compiles to

body {
  font-family: open_sans, Verdana, Helvetica, sans-serif;
  color: #121212;
  background: black url('/images/background2.jpg');
  background-repeat: no-repeat;
  background-position: center;
  background-attachment: fixed;
  background-size: cover;
  margin: 0;
  padding: 0;
}

This used to be documented in the README but then all the stuff was moved from the README to the Wiki and then only partially back to the README. 🙄