GithubHelp home page GithubHelp logo

garden's Introduction

Garden

Garden is a library for rendering CSS in Clojure and ClojureScript. Conceptually similar to Hiccup, it uses vectors to represent rules and maps to represent declarations. It is designed for stylesheet authors who are interested in what's possible when you trade a preprocessor for a programming language.

Table of Contents

Getting Started

Add the following dependency to your project.clj file:

Clojars Project

Garden 1.2.5 and below requires Clojure 1.6.0 and is known to work with ClojureScript 0.0-2342. However, starting with Garden 1.3.0 Garden requires Clojure 1.7 and ClojureScript 1.7.x to leverage a unified syntax with reader conditionals, and other major changes in the compiler and repl in Clojurescript.

Syntax

Garden syntax is very similar to Hiccup. If you're familiar with Hiccup you should feel right at home. If not, don't sweat it!

From your project's root directory start up a new REPL and try the following:

user=> (require '[garden.core :refer [css]])
nil
user=> (css [:body {:font-size "16px"}])
"body{font-size:16px}"

First you'll notice the use of the css function. This function takes an optional map of compiler flags, any number of rules, and returns a string of compiled CSS.

Vectors represent rules in CSS. The first n non-collection elements of a vector depict the rule's selector where n > 0. When n = 0 the rule is not rendered. To produce a rule which selects the <h1> and <h2> HTML elements for example, we simply begin a vector with [:h1 :h2]:

user=> (css [:h1 :h2 {:font-weight "none"}])
"h1,h2{font-weight:none}"

To target child selectors nested vectors may be employed:

user=> (css [:h1 [:a {:text-decoration "none"}]])
"h1 a{text-decoration:none}"
user=> (css [:h1 :h2 [:a {:text-decoration "none"}]])
"h1 a, h2 a{text-decoration:none}"

As in Less/Sass, Garden also supports selectors prefixed with the & character allowing you to reference a parent selector:

user=> (css [:a
             {:font-weight 'normal
              :text-decoration 'none}
             [:&:hover
              {:font-weight 'bold
               :text-decoration 'underline}]])
"a{text-decoration:none;font-weight:normal}a:hover{text-decoration:underline;font-weight:bold}"

A slightly more complex example demonstrating nested vectors with multiple selectors:

user=> (css [:h1 :h2 {:font-weight "normal"}
             [:strong :b {:font-weight "bold"}]])
"h1,h2{font-weight:normal}h1 strong,h1 b,h2 strong,h2 b{font-weight:bold}"

garden.selectors namespace defines a CSSSelector record. It doubles as both a function and a literal (when passed to the css-selector). When the function is called it will return a new instance that possesses the same properties. All arguments to the function must satisfy ICSSSelector.

garden.selectors namespace also defines these macros that create a selector record: defselector, defclass, defid, defpseudoclass and defpseudoelement.

garden.selectors namespace also defines many CSSSelector instances such as:

  • Type selectors a, abbr, address and more
  • Pseudo-classes active, checked, disabled and more
  • Language and negation pseudo-classes lang and not
  • Structural pseudo-classes nth-child, nth-last-child, nth-of-type and nth-last-of-type
  • Pseudo-elements after, before, first-letter and first-line
  • Attribute selectors attr=, attr-contains, attr-starts-with, attr-starts-with*, attr-ends-with and attr-matches
  • Combinators descendant, +, - and >
  • Special selector &

and allows to compose complex selectors such as this:

(defselector *)
(defpseudoclass host [x] x)
(defpseudoelement content)
(> (host (attr :flipped)) content (* last-child))
;; => :host([flipped]) > ::content > *:last-child

garden.selectors namespace also defines a CSS3 selectors's specificity function:

(specificity "#s12:not(FOO)")
;; => 101
(specificity (a hover))
;; => 10

Clojure maps represent CSS declarations where map keys and values represent CSS properties and values respectively. Garden's declaration syntax is a bit more involved than rules and understanding it is important to make the most of the library.

Declaration map keys should either be a string, keyword, or symbol:

user=> (css [:h1 {"font-weight" "normal"}])
"h1{font-weight:normal}"
user=> (css [:h1 {:font-weight "normal"}])
"h1{font-weight:normal}"
user=> (css [:h1 {'font-weight "normal"}])
"h1{font-weight:normal}"

Be aware, Garden makes no attempt to validate your declarations and will not raise an error if other key types are used.

user=> (css [:h1 {30000 "nom-nom"}])
"h1{30000:nom-nom}"

We've already seen strings used as declaration map values, but Garden also supports keywords, symbols, numbers, maps, vectors, and lists in addition.

Custom functions

Since Garden doesn't have wrappers for all the possible CSS functions, sometimes you might need to define the function you need yourself. This is where the defcssfn macro comes in handy. Suppose you want to use the url CSS function, even if it's not available in Garden directly you can just define it yourself by simply:

(defcssfn url)
;; => #'user/url

Which will render like this:

(css (url "http://fonts.googleapis.com/css?family=Lato"))
;; => url(http://fonts.googleapis.com/css?family=Lato)
Strings, keywords, symbols, and numbers

Strings, keywords, symbols, and numbers are rendered as literal CSS values:

user=> (css [:body {:font "16px sans-serif"}])
"body{font:16px sans-serif}"

Be warned, you must escape literal string values yourself:

user=> (css [:pre {:font-family "\"Liberation Mono\", Consolas, monospace"}])
"pre{font-family:\"Liberation Mono\", Consolas, monospace}"

Development

Leiningen commands

Building ClojureScript

lein build-cljs

Starting a Node REPL

lein node-repl

Run Clojure tests, along with a test runner

lein test-clj

Run ClojureScript tests (on Node)

lein test-cljs

Run both Clojure and ClojureScript tests

lein test-cljc

Further Reading & Wiki

Detailed documentation and a developer guide for Syntax, Rules, Declarations, and Plugins is under the community-contributed wiki.

Please contribute!

Help!

This project is looking for team members who can help this project succeed! Specifically of interest are people who can

  • help fix bugs,
  • answer questions,
  • merge pull requests, and
  • deploy new versions.

If you are interested in becoming a team member please open an issue and direct message @noprompt, or direct message @noprompt on Clojurians.

The original author, @noprompt, is a busy person with a family, a job, and other projects. Be aware that it may take some time for pull requests to be evaluated.

Community

Mailing List

Slack

License

Copyright © 2013-2019 Joel Holdbrooks.

Distributed under the Eclipse Public License, the same as Clojure.

garden's People

Contributors

aisamu avatar andreacrotti avatar danielcompton avatar defunctionalize avatar ernestas avatar harold avatar jamesnvc avatar jeluard avatar jffry avatar luontola avatar malcolmsparks avatar maxst avatar meelijane avatar migroh avatar niamu avatar noprompt avatar pavel-klavik avatar prestancedesign avatar priyatam avatar roosta avatar sgrove avatar stevejmp avatar tobereplaced avatar worldsendless avatar wpcarro avatar zehcnas34 avatar zkry avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

garden's Issues

Comments or docstrings for rules

I'm really liking how data-driven this project makes the writing of styles. I imagine having a datastructure that is literally a set of rule vectors, and then passing the whole thing to the css macro for rendering. Kinda like this:

#{[:.red {:color "red"}]
 [:.blue {:color "blue"}]}

But one thing that's missing is comments for each rule. It'd be great if I could define comments/docstrings like in the def and defn macros. So, it'd end up looking like:

#{[:.red "this rule makes text red" {:color "red"}]
  [:.blue "this rule makes text blue" {:color "blue"}]}

Thoughts?

I am rewriting "normalize.css" in clojure using garden

I want to group many variable under one group how should I approach this with the example below:

;;=====================================================================
;; HTML5 display definitions
;;=====================================================================

(def fix-audio-control
"Prevents modern browsers from displaying 'audio' without controls
Remove excess height in iOS5 devices"
[(keyword "audio:not([controls])") {:display "none" :height (em 0)}])

(def fix-display-block
"Corrects block display not defined in IE6/7/8/9 & FF3"
(element->block {:display "block"}))

(def fix-display-inline
"Corrects inline-block display not defined in IE6/7/8/9 & FF3"
(element->inline {:display "inline-block" :_display "inline" :_zoom 1}))

(def fix-hidden
"Addresses styling for 'hidden' attribute not present in IE7/8/9, FF3, S4
Known issue: no IE6 support"
[(keyword "[hidden]") {:display "hidden"}])

I want have all this variable under one group like (def html5-section ...)

Optional docstrings in garden.def

The macros in garden.def could take optional docstrings and meta maps through the use of clojure.tools.macro/name-with-attributes.

This is distinct from issue #4 because it is meant to provide documentation for the developer at development time, not to show up in the CSS output.

This would require a dependency on clojure.tools.macro. If there is interest, I'm happy to do the work.

support for repeated declaration of same property

Hello,

I was trying here to use a cross-browser definition for flex: box, and in CSS terms it would be:

.flex-row {
  display: -webkit-box;
  display: -moz-box;
  display: -webkit-flex;
  display: -ms-flexbox;
  display: box;
  display: flex;
}

The problem is that since garden uses maps for the CSS declarations I couldn't figure out how to repeat same property into the declaration. There is any way to accomplish that?

One parent only child selector

This example is presented in the README as a way to represent child selectors:

(css [:h1 :h2 [:a {:text-decoration "none"]]) ; btw, there is a typo in the README too :}
"h1 a, h2 a{text-decoration:none}"

What if I wanted the corresponding CSS to be:

"h1, h2 a{text-decoration:none}"

instead?

Weird parsing when used on Heroku

Because of the way I've written my prototype web app, CSS gets re-rendered when the project is pushed to Heroku (and dumped in main.css). I noticed that colors get rendered in a really weird way on Heroku. Check it out:

What locally gets rendered as:

  border-color: #6eaedd;
  color: #6eaedd;

On Heroku, gets rendered as:

border-color: red: 110;
  green: 174;
  blue: 221;
  hue: ;
  saturation: ;
  lightness: ;
  alpha: ;;
  color: red: 110;
  green: 174;
  blue: 221;
  hue: ;
  saturation: ;
  lightness: ;
  alpha: ;;

I haven't been able to discern why this happens.

Space vs Comma separation.

The documentation specifies the opposite nesting rule of what actually occurs:

Code:

(css [:p {:font ["16px" "sans-serif"]}])

Result:

"p {\n  font: 16px, sans-serif;\n}"

Documented behavior:

"p{font:16px sans-serif}"

clj 1.5.1 with garden

Just for the record (and a bit of whining also), I'm using Garden in a project that can't use Clojure 1.6.0 for an obscure reason I couldn't completely isolate yet (I doubt I will be able to solve it in the short term). Garden requires Clojure 1.6.0, which will oblige me to downgrade Garden to a version that uses Clojure 1.5.1 until the problem is solved.

Just my personal opinion: Clojure 1.6.0 is too early for libraries. I would use 1.5.1 at most unless there's a good reason otherwise.

Some incorrect CSS being generated on shorthand

Hey Joel,

I kinda noticed something wrong with some of the margin code generated, that probably comes from the library itself. I attached a screenshot to illustrate the printing of a , in between the elements of a shorthand notation, where those values should

  • not contain a comma
  • 0 should prefer over 0px

SCREENSHOT

The garden parts responsible are taken as well, for reference, although I'm fairly sure this is something that originates from the units and/or arithmetic namespaces.

SCREENSHOT

Cheers,
Rob

not compiling successfully first run

When doing lein garden auto, it doesn't compile, and just says Compiling Garden....
Still with lein garden auto running, I touch the .clj file, and the compilation is successful.

Garden license?

Garden currently doesn't specify a license. Is that intended?

Multiple CSS properties of same name

Sometimes for browser compatability, it is desireable to repeat a CSS property name. For example:

background: rgb(...);
background: -moz-linear-gradient(...);
background: -webkit-gradient(...);

Garden uses a hash map to express rules, and hash maps cannot repeat keys.

jQuery.css() has a similar issue, and you can read people working around it here:

http://stackoverflow.com/questions/8457388/build-javascript-object-to-use-with-jquery-css-what-about-duplicate-keys

Is there a way to generate this kind of CSS using garden?

If not, then one idea is to use sets. For example:

(css {:background #{"rgb(...)"
                    "-moz-linear-gradient(...)"
                    "-webkit-gradient(...)"}})

Could produce the desired output.

This assumes that the order doesn't matter, but by using hash maps in the first place we're kind of assuming that CSS rule order doesn't matter within a single selector.

Render CSS to a file

in gaka if I remember correctly you can specify where the group of rules will be saved inside resources?

Improve at-font-face

This seems like a start.

(defn at-font-face [& {:as kwargs}]
  (let [kwargs (->> (select-keys kwargs [:family :weight :style :eot :woff :svg])
                    (remove (comp nil? second))
                    (into {}))
        font-attrs (select-keys kwargs [:family :weight :style])
        srcs (select-keys kwargs [:eot :woff :svg])
        url (cssfn :url)
        format (cssfn :format)]
    ["@font-face"
     {:font font-attrs}
     (when-not (empty? srcs)
       {:src (for [[fmt uri] srcs]
               [(url uri) (format (name fmt))])})]))

(at-font-face
 :family "Family"
 :weight :normal
 :style :normal
 :eot "/path/to/eot")

Result

@font-face {
  font-style: normal;
  font-weight: normal;
  font-family: Family;
  src: url(/path/to/eot) format(eot);
}

Edit: Add url
Edit: Add demonstration

Support for existing CSS resources

One of the killer features of enlive/enfocus (for me at least) is the ability to define snippets/templates based on existing resources. This is a huge win for the common scenario of HTML/CSS designers working independently from developers. I can get some static markup from a designer, define some selectors to extract the pieces I need to build my templates, and when he/she updates the HTML, at best I just drop in the new file, at worst I may have to tweak the selectors and then everything else falls into place.

This would be a great feature for garden to support. I see it basically working like deftemplate/defsnippet in enlive, where you can give it a filename and a list of selectors/transformations. The CSS would be parsed and return the same datastructures used when you are building the css programmatically. Once this infrastructure was in place, it would be straightforward in the future to extend it to support LESS, Stylus, SCSS, etc. by plugging in a different parser.

If someone else is working on this already, speak up and I'll help out however I can. Otherwise, I'm willing to take the lead on adding this feature, but I would like to get feedback and discuss design/implementation details with the rest of the community first.

Garden as middleware / server-side CSS

Turns out garden is pretty darn sweet as middleware. I've synthesized it to some of the samples in Pedestal I was updating for the recent bump to 0.2.x, one of the samples was a template-server using several populate template solutions like hiccup, ST4, comb, enlive etc. I've taken the liberty to add some server-side CSS to the flavor using garden :) While I'm still playing around with some thoughts on abstracting some of these features in Pedestal (and this wouldn't be something I would decide on anyway), I thought it would be nice to share it here. Either way, once I've started to feel more comfortable, people gave some input and such, we could hopefully start develop a more common view on what direction some of the UI side (say widgets/components) the whole Cljs/UI/CSS aspects would interact (it can be a complicated beast) so perhaps we can pave some paths here and there, I don't know.

Since I'll be actively working on this coming week, I'd appreciate any thoughts, input, questions and what not. Here's the currently used link to the code (its part of a larger media repo I use, so if you clone theres tons of screenshots etc in them, if someone wants I can separate them now, else it'll probably be done somewhere next week).

https://github.com/clojens/app-tutorial/tree/refactor/media/new-samples/template-server

p.s. I assumed you wouldn't have objections to the inclusion, if so let me know and I'll tear it out :)

Readme outdated?

readme is outdated?
couldn't even find previous garden.core/css elsewhere in your code

Lein plugin

It would really helpful if garden had lein plugin for generation css files from "garden " format and automatic regeneration. Similar to lein-haml-sass.
We want to try garden in our little project and absence of such plugin is stopping us. I can help you with it if you want.

java.lang.RuntimeException: Unable to resolve symbol: record? in this context, compiling:(garden/util.clj:95:22)

I followed the readme to integrate Garden with Leiningen, but lein do cljsbuild clean, cljsbuild auto debug results in an error:

# lein do cljsbuild clean, cljsbuild auto debug
Error: problem requiring leiningen.garden/activate hook
java.lang.RuntimeException: Unable to resolve symbol: record? in this context, compiling:(garden/util.clj:95:22)
[…]

Excerpts from project.clj:

[…]
  :dependencies [[org.clojure/clojure "1.6.0"]
                 [org.clojure/clojurescript "0.0-2311"]
[…]
  :plugins [[lein-cljsbuild "1.0.3"]
            [lein-garden "0.2.0"]]

  :hooks [leiningen.cljsbuild
          leiningen.garden]

  :source-paths ["src"]

  :garden {:builds [{:id "main-style"
                     :stylesheet ….style/main
                     :compiler {:output-to "main.css"
                                :pretty-print? false}}]}
[…]

One note: The style.clj file does not yet exist.

lein-garden-0.1.9 works without these issues.

Re-add Object/toString CSSColor implementation

Continued from: eb16db6#commitcomment-4614132

Commit eb16db6 included the following hunk:

-  #+clj Object #+cljs default
-  (toString [this]
-    (as-hex this)))
+  ;;Introduces an infinite loop when as-hex throws an exception
+  ;;Object
+  ;;(toString [this]
+  ;;  (as-hex this))

This was presumably done in the interest of ClojureScript compatibility, however, the implicit as-hex string conversion of CSSColor instances is very convenient:

(css [:elem {:box-shadow (str "0px 1px 1px " deep-blue)}])

In the interests of bringing back this feature I propose either:

  1. Change as-hex and related functions to not throw Exceptions in favor of using default values and clipping out-of-bound values
  2. Wrap (as-hex this) in a try catch and return a default string.

This is not a major issue, of course, but it would be nice.

Thanks!

CSS3 Transitions, Transforms, Animation, Filters and such

Thought this might be worth its own topic: CSS3 Transitions, Transforms and Animation

Sometimes I love Clojure, at other times I feel I have too many options. Anyway that might be why now and then I'll drop some pseudo code or just objects here, since I don't plan to perfect every angle of things without prior discussion :)

Bezier curves

This is a little play with several options for governing the fx part of CSS, perhaps a little restrictive and not my best coding practices but intended more for discussion, base-line and what not.

(def not-nil? (complement nil?))
(defn transition-property? [in] (not-nil? (valid-transition-properties in)))
(defn perc? [x] (= :% (second (first (seq x)))))
(defn calc? [_] nil)
(defn visibility? [x] (not-nil? (get #{:visible :hidden :collapse} x)))

(defn ease
  "Take a single 3-tuple of key, value and property. Key will lookup the FX in the
  curves map and apply the correct values, value (could be) type checked against a map of
  valid CSS properties/HTML attributes which would have a collection of predicate functions
  to test against the expression value and finally, will check if the property itself is one
  allowed by the standard/spec."
  [k v prop]
  {:pre [(or (string? prop) (symbol? prop) (keyword? prop))]}
  (if-let [valid? (transition-property? (keyword prop))]
    (let [p (if (keyword? prop) (name prop) prop)]
      (str p " " v " cubic-bezier" (k curves)))))


(def curves
  "One of the most often overlooked features of CSS transitions is the ability to specify a
  cubic-bezier timing function. This is because you get a bunch of easing options out of the
  standards-based box: ease, ease-in, ease-out, ease-in-out, linear."
  {:linear       '(0.250, 0.250, 0.750, 0.750)  :ease         '(0.250, 0.100, 0.250, 1.000)
   :in           '(0.420, 0.000, 1.000, 1.000)  :out          '(0.000, 0.000, 0.580, 1.000)
   :in-out       '(0.420, 0.000, 0.580, 1.000)  :in-quad      '(0.550, 0.085, 0.680, 0.530)
   :in-cubic     '(0.550, 0.055, 0.675, 0.190)  :in-quart     '(0.895, 0.030, 0.685, 0.220)
   :in-quint     '(0.755, 0.050, 0.855, 0.060)  :in-sine      '(0.470, 0.000, 0.745, 0.715)
   :in-expo      '(0.950, 0.050, 0.795, 0.035)  :in-circ      '(0.600, 0.040, 0.980, 0.335)
   :in-back      '(0.600, -0.280, 0.735, 0.045) :out-quad     '(0.250, 0.460, 0.450, 0.940)
   :out-cubic    '(0.215, 0.610, 0.355, 1.000)  :out-quart    '(0.165, 0.840, 0.440, 1.000)
   :out-quint    '(0.230, 1.000, 0.320, 1.000)  :out-sine     '(0.390, 0.575, 0.565, 1.000)
   :out-expo     '(0.190, 1.000, 0.220, 1.000)  :out-circ     '(0.075, 0.820, 0.165, 1.000)
   :out-back     '(0.175, 0.885, 0.320, 1.275)  :in-out-quad  '(0.455, 0.030, 0.515, 0.955)
   :in-out-cubic '(0.645, 0.045, 0.355, 1.000)  :in-out-quart '(0.770, 0.000, 0.175, 1.000)
   :in-out-quint '(0.860, 0.000, 0.070, 1.000)  :in-out-sine  '(0.445, 0.050, 0.550, 0.950)
   :in-out-expo  '(1.000, 0.000, 0.000, 1.000)  :in-out-circ  '(0.785, 0.135, 0.150, 0.860)
   :in-out-back  '(0.680, -0.550, 0.265, 1.550) :custom       '(0.500, 0.250, 0.500, 0.750) })

(def valid-transition-properties
  "Simple preliminary setup of how a possible map with valid properties and type
  checking functions could look like. From official CSS spec. Would need to check those
  predicates against value `v` which AND / OR have to pass. (not implemented)
  "
  {:background-color      [color?]                :background-position [list? length? perc? calc?]
   :border-bottom-color   [color?]                :border-bottom-width [length?]
   :border-left-color     [color?]                :border-left-width   [length?]
   :border-right-color    [color?]                :border-right-width  [length?]
   :border-spacing        [list? length?]         :border-top-color    [color?]
   :border-top-width      [length?]               :bottom              [length? perc? calc?]
   :clip                  [color?]                :color               [color?]
   :font-size             [length?]               :font-weight         [(or 200 300 400 500 600 700 800)]
   :height                [length? perc? calc?]   :left                [length? perc? calc?]
   :letter-spacing        [length?]               :line-height         [(or (number? 'x) (length? 'x))]
   :margin-bottom         [length?]               :margin-left         [length?]
   :margin-right          [length?]               :margin-top          [length?]
   :max-height            [length? perc? calc?]   :max-width           [length? perc? calc?]
   :min-height            [length? perc? calc?]   :min-width           [length? perc? calc?]
   :opacity               [number?]               :outline-color       [color?]
   :outline-width         [length?]               :padding-bottom      [length?]
   :padding-left          [length?]               :padding-right       [length?]
   :padding-top           [length?]               :right               [length? perc? calc?]
   :text-indent           [length? perc? calc?]   :text-shadow         '[shadow list]
   :top                   [length? perc? calc?]   :vertical-align      [length?]
   :visibility            [visibility?]           :width               [length? perc? calc?]
   :word-spacing          [length?]               :z-index             [integer?]
   :all '[all]
   })


;{:-webkit-transition (ease :in-out "2s" :all)}
(ease :in-out "2s" :all)
;=> "all 2s cubic-bezier(0.42 0.0 0.58 1.0)"

;;-webkit-transition: all 600ms cubic-bezier(0.950, 0.050, 0.795, 0.035); 
;;-webkit-transition-timing-function: cubic-bezier(0.950, 0.050, 0.795, 0.035); 

The above is intended to toy around a little with the order of arguments.

As I noticed you have this stuff on your todo list among others, figured you may find useful, at some time or another, no rush. If needed we can discuss any ideas, thoughts, plans on the whole transition,transformation,animate field here.

Namespace typo

You wrote "arithemetic", but correct would be "arithmetic".

at-media does not allow for non-standard media queries

First, I want to say that I like garden. A clojurescript port would be very nice... using the library for in-browser dynamic CSS generation for media queries would be awesome but I digress.

My issue is that non-standard media queries are not recognized.
e.g. at the repl:
repl> (css (at-media {:screen true :-webkit-min-device-pixel-ratio "2"} [:html {:width "480px"}]))
"@media screen{html{width:480px}}"

Could you please allow for generic media queries to be made so that vendor specific media queries can be created? I think something as simple as wrapping parens around anything that has a non-boolean value {:query "value"} -> (query:value) and anything with a boolean value like {:query true} -> query

Thanks!

rgba incorrectly rendered

With 1.1.2 (rgba 252 252 252 0.7) gets rendered as hsla(0, 0, 98.82352941176471%, 0.7) which is apparently incorrect as the second value cannot be 0 (chrome complains).

Output differences between regular REPL and Light Table

Hey guys, I hope one of you has an idea where the following discrepancy could be coming from since I really don't think I've seen this much diff between LT and regular REPL output so my first stop would be here I guess.

update: Ok so I narrowed this down a bit more

file: compiler.clj
(defn- extract-media-query
  "Extracts media query information from rule meta data."
  [rule]
  (when-let [m (meta rule)] ;; <=== this bad boy
    ;; The `:doc` key is reserved for CSS comments.
    (dissoc m :doc)
    ))

The problem is that since LT has another writer hooked up, or at least me thinks that is, so I need to resolve meta from vars like (meta #'first) but I'm not sure, keep digging for now.

What are your thoughts on testing the output CSS?

Consider this variable

(def normalize-base
[[:html {:font-family "sans-serif"
:-ms-text-size-adjust (percent 100)
:-webkit-text-size-adjust (percent 100)}]
[:body {:margin 0}]])

And its test

expect "html {\n font-family: sans-serif;\n -ms-text-size-adjust: 100%;\n -webkit-text-size-adjust: 100%;\n}\n\nbody {\n margin: 0;\n}"
(css {:pretty-print? true} normalize-base))

Here the expected doesn't match but only the order they come in. The CSS itself is valid.

I know this is related to the use of maps, but this make testing problematic. What are your thoughts?

Any approaches for formatting/splitting nested Clojure vectors for readability?

Here's some hastily-written CSS I took from a recent project where selector hierarchy isn't immediately apparent due to one-space indentation on datastructures:

[:.user-form
 {:background "#444"
  :font-size "32px"
  :margin "10px 0"
  :padding "10px"
  :color "#bbb"}
 [:label
  {:display "none"}]
 [:input
  {:font-size "32px"
   :margin 0
   :padding "0 5px"
   :line-height "40px"
   :border "5px solid black"
   :height "40px"}]
 [:.user-submit
  {:height "50px"
   :pointer "cursor"
   :margin "0 0 0 10px"
   :background "#2bc253"}
  [:&:hover
   {:background "#5cdb7e"}]]
 [:.user-input
  {:color "#bbb"
   :background "rgba(0, 0, 0, 0.16)"}]]

The obvious solution is to split/abstract/mixin this kind of stuff apart, but this is the kind of CSS I'm working with the majority of the time during development when it's too early and pro tem to recognize opportunity for abstraction.

Here's an example of one approach I sometimes take:

[:.user-form
 {:background "#444"
  :font-size "32px"
  :margin "10px 0"
  :padding "10px"
  :color "#bbb"}]

[:.user-form
 [:label
  {:display "none"}]]

[:.user-form
 [:input
  {:font-size "32px"
   :margin 0
   :padding "0 5px"
   :line-height "40px"
   :border "5px solid black"
   :height "40px"}]]

[:user-form
 [:.user-submit
  {:height "50px"
   :pointer "cursor"
   :margin "0 0 0 10px"
   :background "#2bc253"}
  [:&:hover
   {:background "#5cdb7e"}]]]

[:user-form
 [:.user-input
  {:color "#bbb"
   :background "rgba(0, 0, 0, 0.16)"}]]

Any other ideas? This is a typical issue that must be managed in any nested code (Python, Sass, Node callbacks, Yaml) but slightly exacerbated for Clojure datastructures.

prefixing (snippet included)

Hey, just stumbled on this last night and banged together a simple style sheet. Looks fine. I found the following to be a great time saver for mozilla/webkit/pure html repetition:

(defn prefix [ps]
  (fn [x y]
    [:& (into {} (map (fn [z] [(str z (name x)) y]) ps))]))

(def mwk (prefix [nil "-moz-" "-webkit-"]))

which then allows

user=> (css [:.btn {:opacity 1} (mwk :user-select :none)])
.btn{opacity:1}.btn{-webkit-user-select:none;-moz-user-select:none;user-select:none}

I don't know if you want something like that in the lib, or as a usage example or what have you. but I figured I'd show you.

And, not for nothing, 'arithmetic' only had one 'e'.

cheers,

chris

rem unit support

I can see the rem unit definition is commented right now. Is there some specific issues around its support?

Using CSS with variable output-style values.

So I have two sets of css stylesheets where expanded and compressed files live in publics/resources/css and public-war/css, respectively. I want to be able to export everything in one go and I wrote a wrapper function which would export either the expanded or compressed versions of file to the appropriate dir. However, I ran into an issue I can't solve.

My issue is that I don't know why I can't give the css macro the value for output-style directly and instead I have to resort to using cond in export-css-hack.

(def styles
  [[:h1 {:font-weight "normal"}]
   [:a {:text-decoration "none"}]])

(defn export-css-desired
  [css-vector output-style]
  (css {:output-style output-style} css-vector))

(defn export-css-hack
  [css-vector output-style]
    (cond (= output-style :expanded)
          (css {:output-style :expanded} css-vector)
          (= output-style :compressed)
          (css {:output-style :compressed} css-vector)))

I would expect export-css-desired and export-css-hack to give the same results. They however, do not.

repl> (export-css-hack styles :compressed)
"h1{font-weight:normal}a{text-decoration:none}"
> (export-css-hack styles :expanded)
"h1 {\n  font-weight: normal;\n}\n\na {\n  text-decoration: none;\n}"
> (export-css-desired styles :expanded)
"h1{font-weight:normal}a{text-decoration:none}"

I would like to better understand what is going on here. Thanks!

Bad composability in docs -- how to do it properly?

The documentation has the following example:

user=> (css [:p {:font [["16px" 'Helvetica] 'Arial 'sans-serif]}])
"p{font:16px Helvetica,Arial,sans-serif}"

I want to be able to set my fonts in a variable, like:

(def fonts ["Open Sans" "Helvetica" "sans-serif"])

My questions are:

  1. How can I use a fonts vector to write css properly?
  2. How should we handle escaping fonts when necessary? -- for example, with "Open Sans", we actually have to do ""Open Sans"".

My ideal world looks like what we had in the pre-1.0 releases:

[:p {:font ["16px" ["Open Sans" "Helvetica" "sans-serif"]]}]

On a side note... the docs are slightly misleading. You must do:

(css {:pretty-print? false} [:p {:font [["16px" 'Helvetica] 'Arial 'sans-serif]}])

Add scaling (%) color functions.

Right now, garden.color's color-update functions simply add or subtract a fixed amount from the percent value.

It's useful, but sometimes you want to instead scale a value.

For example, darkening a:hover by a fixed 15 is more visible when the contrast between your colors are low, and less visible when the contrast happens to be high.

In such a case, darkening instead by 15% would create the same aesthetic change regardless of the color scheme.

I've implemented some: https://github.com/danneu/garden-compass/blob/master/src/garden_compass/helpers/colors.clj#L57-L65

Make compress-stylesheet public

compress-stylesheet is a utility function to use the YUI CssCompressor.

I have a use case where I want to use normalize.css with a set of garden rules. I want to do:

(compress-stylesheet (str normalize-css (css rules)))

Other notes:

  • The compress-stylesheet function should probably use with-open instead of let.
  • We could pass in an optional line-break-position argument, which when nil, uses -1, otherwise passes it to the .compress method.
  • Maybe another name is more appropriate? compress-css-string?
  • When {:pretty-print? true}, the compressor isn't used, so we could make YUI an optional dependency.

multiple values px / generator

How do I write a generator like:

-moz-linear-gradient(top, #a90329 0%, #900000 44%, #6d0019 100%)

or a property with multiple px values like:

:padding "5px 0px 5px 50px"

any way more idiomatic than this?

Prefixing values

For some CSS rules, it is the value that needs to be prefixed rather than the selector. The particular case I'm running into is flex box, where i need to write

display: flex
display: -webkit-flex

in order to get it to work in Safari. How would I go about achieving this?

Add Preamble Compilation Option

Adding the preamble compilation option would help streamline the current front-end workflow with Garden.

Since with SCSS you can just include the files directly (as valid CSS is valid SCSS) with Garden it is probably better to create something akin to the 'preamble' from ClojureScript.

Syntax for complex selector

With new w3c specifications like ShadowDOM you can find complex CSS selector like :host([flipped]) > ::content > *:last-child.

What's the best way to define those?

duplicate keys how to handle?

How to handle duplicate keys like in:

background: #a90329;
background: -moz-linear-gradient(top, #a90329 0%, #900000 44%, #6d0019 100%);

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.