Giter Club home page Giter Club logo

cljs-css-modules's Introduction

Css Modules in ClojureScript

Clojars Project

First if you don't know what's a css modules, you should definitely read the specification: https://github.com/css-modules/css-modules

Using cljs-css-modules, you won't write pure CSS, but you'll use garden syntax to write your style in ClojureScript.
(Garden basically allows you to use any feature of pure css, so no worries you're not losing any power here).

The idea of cljs-css-modules is to localise every classes (and soon animations) you define through the defstyle macro.

Example Project

gmp26 put together a repository porting a css-modules project over to a cljs-css-modules/cljs one.

You can check it out, to see how this library can be used in a real project:

Usage

Add this to your project.clj:

You need to define your style using the defstyle macro.

Your style will be written using garden syntax, so spend some time reading the doc.

Each time you'll define some style using defstyle, this style will be localised (every classes and animations), translated to CSS, and automatically injected into the <head> tag. This works perfectly with figwheel, and you'll get live style reloading out of the box.

(If you come from the javascript world and you've used webpack before, it replaces both css-loader and style-loader).

Example:

Define your style:

(ns yourapp.namespace1
  (:require [cljs-css-modules.macro :refer-macros [defstyle]]))

(defstyle style

  (at-media {:max-width "200px"}

            [".mobile-style-1" {:margin "5px"}]

            [".mobile-style-2" {:margin "10px"}])

  [".container" {:background-color "blue"
                  :font-size 55}
    ["a" {:color "green"}]
    ["&:hover" {:background-color "black"}]]

   [".text" {:font-size 14
             :color "brown"}]

   (at-keyframes "keyframe-1" [:from {:a 50}]
                          [:to  {:b 50}])

   ["@keyframes keyframe-2" [:from {:a 50}]
                          [:to  {:b 50}]]

   [".title" {:background-color "blue"
              :font-size 60}]

   [".title2" {:font-size 40
               :color "red"}])

The localised classes/keyframes will be available in the style object created. (Note: including classes in media queries).

(:container style) ;; => returns the unique generated class for ".container"
(:mobile-style-1 style) ;; => returns the unique generated class for ".mobile-style-1"

To use your style, you just need to inject them wherever you need:

For instance with reagent:

(defn simple-component []
  [:div {:class-name (:container style)}
   [:h1 {:class-name (:title style)} "I am a big title"]
   [:h1 {:class-name (:title2 style)} "I am smaller title"]
   [:p {:class-name (:text style)}
    "Here goes some random text"]])

Media queries

To define a media query you need to use the (at-media) form, and nest your style in it. It's the same as garden's syntax, here is the documentation: https://github.com/noprompt/garden/wiki/Media-Queries

Example:

(defstyle style
  (at-media {:max-width "400px"}

            [".mobile-style" {:margin "5px"}])

  (at-media {:min-width "400px"
             :max-width "800px"}

            [".tablet-style-1" {:margin "5px"}]

            [".tablet-style-2" {:margin "10px"}]))

This will localise all the classes in your media queries, here: .mobile-style, .tablet-style-1, .tablet-style-2.

Note: Using cljs-css-modules, you don't need to import the at-media function from garden's library. The macro will recognise the at-media symbol.

Keyframes

To define an animation you need to use the (at-keyframes) form, or a string like "@keyframes animation-name":

Example:

(defstyle style

  (at-keyframes "animation-1"
                [:from {:top "0px"}]
                [:to {:top "200px"}])

  (at-keyframes "animation-2"
                [:from {:top "0px"}]
                [:to {:top "250px"}])

  ["@keyframes animation-3" [:from {:top "0px"}]
                            [:to {:top "250px"}]])

This will localise all the animations, here: animation-1, animation-2, animation-3.

Note: Using cljs-css-modules, you don't need to import the at-keyframes function from garden's library. The macro will recognise the at-keyframes symbol.

From Clojure

If you use the macro from clojure (and not clojurescript), it will define a map containing both the generated css and the map between original selectors and localised selectors.

(defstyle style

  {:pretty-print? false}

  (at-keyframes "animation-1"
                [:from {:top "0px"}]
                [:to {:top "200px"}])

  (at-keyframes "animation-2"
                [:from {:top "0px"}]
                [:to {:top "250px"}])

  ["@keyframes animation-3" [:from {:top "0px"}]
                            [:to {:top "250px"}]])

In this case style would be the following map:

{:map {:animation-1 "animation-1--G__1524"
       :animation-2 "animation-2--G__1524"
       :animation-3 "animation-3--G__1524"}
 :css "@keyframes animation-1--G__1524{from{top:0}to{top:200px}}@keyframes animation-2--G__1524{from{top:0}to{top:250px}}@keyframes animation-3--G__1524{from{top:0}to{top:250px}}"}

You can then do whatever you want with these, and use it for you server side rendered apps!

Note

You might want to consider https://github.com/mhallin/forest which is not based on garden and provides the same kind of features using its own DSL.

License

Copyright © 2016 Matthieu Béteille

Distributed under the Eclipse Public License version 1.0

cljs-css-modules's People

Contributors

bnoguchi avatar matthieu-beteille 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

Watchers

 avatar  avatar  avatar  avatar

cljs-css-modules's Issues

Unable to resolve symbol

I'm getting this in the repl.
clojure.lang.Compiler$CompilerException: java.lang.RuntimeException: Unable to resolve symbol: defstyle in this context, compiling:(/var/folders/yq/n5bg23w14_73jpfnb1zvn0vw0000gn/T/boot.user2040401869853839340.clj:1:1) java.lang.RuntimeException: Unable to resolve symbol: defstyle in this context

Q: Is it possible for this to be made into a cljc?

Firstly I would like to say thank you! I've been waiting for someone to bring this to the Clojure ecosystem.

I'm currently working on generating static sites to host on Netlify using Rum and Boot. Having CSS Modules is the last piece of the puzzle to the devflow I am striving for. Is this something on the road map? How long would it take? If it is possible to come soon I am prepared to start using it now and allow my site to be used as an example.

Consistent Class Names on Server and Client?

I like that this library works on both server and client side. Yesterday I've been messing around with universal rendering using Rum and like that I can get styles generated on the server and client. The only issue right now that I'm having is because the names are slightly different on the server and client I get a React warning where because things don't match up I lose the server rendering benefits:

Warning: React attempted to reuse markup in a container but the checksum was invalid.
This generally means that you are using server rendering and the markup generated on
the server was not what the client was expecting. React injected new markup to
compensate which works but you have lost many of the benefits of server rendering.
Instead, figure out why the markup being generated is different on the client or
server:
 (client) class="container--G__40510"
 (server) class="container--G__12410"

I'm wondering if there could be an approach to get consistent class names.

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.