Préfixer automatiquement les css

Comment ajouter automatiquement les préfixes vendeurs aux css ?

18 mars 2015

Rappels

Les préfixes vendeurs sont des propriétés propriétaires des éditeurs de navigateurs ( vendors ), qui doivent être préfixées d'un tiret et d'un code correspondant au moteur les exploitant : -moz- pour Gecko ( Mozilla ), -ms- pour Microsoft ( Internet Explorer ), -webkit- pour Webkit ( Chrome, Safari, Android...). -o- pour Opera, ...

css est un langage informatique qui permet de formater l'affichage des documents html.

less est un pré-processeur de css, c'est-à-dire qu'il permet d'étendre le langage css, en ajoutant des fonctionnalités comme la possibilité d'utiliser des variables, des fonctions et bien d'autres fonctionnalités qui permettent de fabriquer des css de manière plus confortable, less est utilisé par bootstrap pour générer son css.

autoprefixer est un outil libre qui permet de parser les css et d'y ajouter les préfixes vendeurs, répertoriés dans la base Can I Use.

grunt est un outil libre qui permet d'automatiser des tâches répétitives, par exemple, compiler less en css et préfixer les css.

Exemple d'utilisation

Notre besoin, pour des raisons évidentes (gain de temps, éviter les oublis et les erreurs de préfixage), était d'écrire normalement les css selon les spécifications W3C sans nous soucier des préfixes vendeurs. Nous avons donc opté pour la solution autoprefixer en plugin (grunt-postcss) avec grunt pour son utilisation simple et flexible.

Pré-requis

node.js doit être installé, ce logiciel libre permet d'exécuter du javascript côté serveur, il est nécessaire au fonctionnement de grunt.

Installer grunt-cli

grunt-cli est l'interface de commande.

grunt-cli permet d'exécuter la version de grunt qui a été configurée dans un fichier gruntfile.js. Ceci permet d'utiliser différentes versions de grunt installées sur une même machine.

En mode administrateur, exécuter la ligne de commande ci-dessous :

npm install -g grunt-cli

Cela affiche :

C:\Users\GLICER\AppData\Roaming\npm\grunt -> C:\Users\GLICER\AppData\Roaming\npm\node_modules\grunt-cli\bin\grunt
grunt-cli@0.1.13 C:\Users\GLICER\AppData\Roaming\npm\node_modules\grunt-cli
├── resolve@0.3.1
├── nopt@1.0.10 (abbrev@1.0.5)
└── findup-sync@0.1.3 (lodash@2.4.1, glob@3.2.11)

Préparer un nouveau projet grunt

grunt a besoin d'un fichier package.json et d'un fichier gruntfile.js qui doivent être situés dans le même répertoire.

package.json : Contient la liste des composants grunt nécessaires.

gruntfile.js : Contient la liste des tâches à exécuter.

Nos fichiers sont organisés comme ci-dessous :

├───gruntproject
│       gruntfile.js
│       package.json

└───src
    └───less
            style.less

Exemple de fichier style.less

@gray-darker: #222;
@boxShadowColor: #999;

input {
    background-color: @gray-darker;
    border-style: none;
    color: #fff;
    padding: 5px;

    &::placeholder {
        color: white;
        opacity: 1;
        text-overflow: ellipsis;
    }
}

.list-group-item {
    margin-bottom: 15px;
    box-shadow: 1px 1px 1px @boxShadowColor;
    cursor: pointer;
}

.icon-search-bounce {
    animation-name: hbounce;
    transform-origin: 50% 50%;
    transition-property: transform, all;
    animation-duration: 1s;
    animation-delay: 1s;
    animation-iteration-count: 3;
}

@keyframes hbounce {
    0% {
        transform: translateX(-100%);
        opacity: 0;
    }
    100% {
        transform: translateX(0%);
        opacity: 1;
    }
}

package.json

Dans notre cas nous avons besoin du composant grunt-contrib-less qui permet de compiler un fichier less en css et du composant grunt-autoprefixer qui permet de préfixer le css.

{
    "name": "nom-du-projet",
    "version": "0.1.0",
    "devDependencies": {
        "grunt": "~0.4.2",
        "grunt-contrib-less": "~0.9.0",
        "grunt-autoprefixer" : "~2.2.0"
    }
}

gruntfile.js

Nous devons configurer les options des composants grunt-contrib-less et grunt-autoprefixer.

module.exports = function (grunt)
{
    // Configuration
    grunt.initConfig({
        pkg: grunt.file.readJSON('package.json'),
        less: {
            development: {
                src: '../src/less/style.less',  // fichier less à compiler
                dest: '../src/css/style.css' // nouveau fichier css compilé
            }
        },
        autoprefixer: {
            developement: {
                expand: true,
                flatten: true,
                src: '../src/css/*.css', // fichiers css à préfixer
                dest: '../build/' //fichiers css préfixés
            }
        }
    });

    // Charge le composant qui permet de compiler le less en css
    grunt.loadNpmTasks('grunt-contrib-less');

    // Charge le composant qui permet de préfixer les css
    grunt.loadNpmTasks('grunt-autoprefixer');

    // Tâches à exécuter par défaut
    grunt.registerTask('default', ['less', 'autoprefixer']);
};

Installer les composants

En mode administrateur, depuis le même répertoire que le fichier package.json, exécuter la ligne de commande ci-dessous :

npm install

Cela affiche :

npm WARN package.json nom-du-projet@0.1.0 No description
npm WARN package.json nom-du-projet@0.1.0 No repository field.
npm WARN package.json nom-du-projet@0.1.0 No README data
grunt@0.4.5 node_modules\grunt
├── dateformat@1.0.2-1.2.3
├── which@1.0.9
├── eventemitter2@0.4.14
├── getobject@0.1.0
├── colors@0.6.2
├── rimraf@2.2.8
├── async@0.1.22
├── grunt-legacy-util@0.2.0
├── hooker@0.2.3
├── exit@0.1.2
├── nopt@1.0.10 (abbrev@1.0.5)
├── lodash@0.9.2
├── minimatch@0.2.14 (sigmund@1.0.0, lru-cache@2.5.0)
├── glob@3.1.21 (inherits@1.0.0, graceful-fs@1.2.3)
├── coffee-script@1.3.3
├── underscore.string@2.2.1
├── iconv-lite@0.2.11
├── findup-sync@0.1.3 (glob@3.2.11, lodash@2.4.1)
├── grunt-legacy-log@0.1.1 (underscore.string@2.3.3, lodash@2.4.1)
└── js-yaml@2.0.5 (esprima@1.0.4, argparse@0.1.16)

grunt-autoprefixer@2.2.0 node_modules\grunt-autoprefixer
├── diff@1.2.2
├── chalk@0.5.1 (ansi-styles@1.1.0, escape-string-regexp@1.0.3, supports-color@0.2.0, has-ansi@0.1.0, strip-ansi@0.3.0)
└── autoprefixer-core@5.1.7 (num2fraction@1.0.1, browserslist@0.2.0, postcss@4.0.6, caniuse-db@1.0.30000094)

grunt-contrib-less@0.9.0 node_modules\grunt-contrib-less
├── chalk@0.4.0 (has-color@0.1.7, ansi-styles@1.0.0, strip-ansi@0.1.1)
├── grunt-lib-contrib@0.6.1 (zlib-browserify@0.0.1)
└── less@1.6.3 (mime@1.2.11, mkdirp@0.3.5, source-map@0.1.43, clean-css@2.0.8, request@2.53.0)

Exécuter les tâches

Depuis le même répertoire que gruntfile.js, exécuter la ligne de commande ci-dessous :

grunt

Cela affiche :

Running "less:development" (less) task
File ../src/css/style.css created.

Running "autoprefixer:developement" (autoprefixer) task
File ../build/style.css created.

Done, without errors.

ou en spécifiant le chemin du fichier gruntfile.js :

grunt --gruntfile gruntproject/gruntfile.js

Arborescence finale

├───build
│       style.css

├───gruntproject
│   │   gruntfile.js
│   │   package.json
│   │
│   └───node_modules
│       ├───grunt
│       ├───grunt-autoprefixer
│       └───grunt-contrib-less
└───src
    ├───css
    │       style.css

    └───less
            style.less

Fichier css final

input {
    background-color: #222222;
    border-style: none;
    color: #fff;
    padding: 5px;
}

input::-webkit-input-placeholder {
    color: white;
    opacity: 1;
    text-overflow: ellipsis;
}

input::-moz-placeholder {
    color: white;
    opacity: 1;
    text-overflow: ellipsis;
}

input:-ms-input-placeholder {
    color: white;
    opacity: 1;
    text-overflow: ellipsis;
}

input::placeholder {
    color: white;
    opacity: 1;
    text-overflow: ellipsis;
}

.list-group-item {
    margin-bottom: 15px;
    box-shadow: 1px 1px 1px #999999;
    cursor: pointer;
}

.icon-search-bounce {
    -webkit-animation-name: hbounce;
    animation-name: hbounce;
    -webkit-transform-origin: 50% 50%;
    -ms-transform-origin: 50% 50%;
    transform-origin: 50% 50%;
    -webkit-transition-property: -webkit-transform, all;
    transition-property: transform, all;
    -webkit-animation-duration: 1s;
    animation-duration: 1s;
    -webkit-animation-delay: 1s;
    animation-delay: 1s;
    -webkit-animation-iteration-count: 3;
    animation-iteration-count: 3;
}

@-webkit-keyframes hbounce {
    0% {
        -webkit-transform: translateX(-100%);
        transform: translateX(-100%);
        opacity: 0;
    }
    100% {
        -webkit-transform: translateX(0%);
        transform: translateX(0%);
        opacity: 1;
    }
}

@keyframes hbounce {
    0% {
        -webkit-transform: translateX(-100%);
        transform: translateX(-100%);
        opacity: 0;
    }
    100% {
        -webkit-transform: translateX(0%);
        transform: translateX(0%);
        opacity: 1;
    }
}

Versions des logiciels et langages utilisés