web-mode.el is an autonomous emacs major-mode for editing web templates.
HTML documents can embed parts (CSS / JavaScript) and blocks (client / server side).

Native Features


html php css js
Screencast on YouTube (prefer HD Quality)


As a result, a block can be located in a part that is embedded in an HTML document.


You can download this mode here.

A GitHub repository is available: http://github.com/fxbois/web-mode/

web-mode.el is also available on melpa.

web-mode.el is GPL and Free Software.


First drop the file web-mode.el in a directory defined in your load-path.
Then, add in your .emacs (require 'web-mode) (add-to-list 'auto-mode-alist '("\\.phtml\\'" . web-mode)) (add-to-list 'auto-mode-alist '("\\.tpl\\.php\\'" . web-mode)) (add-to-list 'auto-mode-alist '("\\.[agj]sp\\'" . web-mode)) (add-to-list 'auto-mode-alist '("\\.as[cp]x\\'" . web-mode)) (add-to-list 'auto-mode-alist '("\\.erb\\'" . web-mode)) (add-to-list 'auto-mode-alist '("\\.mustache\\'" . web-mode)) (add-to-list 'auto-mode-alist '("\\.djhtml\\'" . web-mode))

Using web-mode for editing plain HTML files can be done this way (add-to-list 'auto-mode-alist '("\\.html?\\'" . web-mode))

You can also edit plain js, jsx, css, scss, xml files.

Associate an engine

A specific engine can be forced with web-mode-engines-alist.

(setq web-mode-engines-alist '(("php" . "\\.phtml\\'") ("blade" . "\\.blade\\.")) )

Using this association list is required as soon as the file extension is unknown (by web-mode) or is too general (e.g. *.html). In summary, you may have to set both auto-mode-alist and web-mode-engines-alist.

Since the version v10, you can also put a fragment like -*- engine:ENGINE_NAME -*- in a comment at the beginning of your template (web-mode-enable-engine-detection must be set to t in your .emacs)

<?php /* -*- engine:php -*- */ ?> <span><?=$x?></span>

The recognized file extensions are listed in the Engine families paragraph.


The first customisations can be put in a hook like this (defun my-web-mode-hook () "Hooks for Web mode." (setq web-mode-markup-indent-offset 2) ) (add-hook 'web-mode-hook 'my-web-mode-hook)

The customisations below should not be put in the hook. Declare them before loading web-mode.el



  • M-; comment / uncomment line(s)
  • C-c C-f toggle folding on a tag/block
  • C-c C-i indent entire buffer
  • C-c C-m mark and expand
  • C-c C-s insert snippet
  • C-c C-w toggle display of invalid whitespaces


  • C-c C-d d show tag mismatch
  • C-c C-d e replace HTML entities
  • C-c C-d n normalize
  • C-c C-d q replace dumb quotes
  • C-c C-d t traverse dom tree
  • C-c C-d x xpath


  • C-c C-b c block close
  • C-c C-b b block beginning
  • C-c C-b e block end
  • C-c C-b p previous block
  • C-c C-b n next block
  • C-c C-b k block kill
  • C-c C-b s block select

HTML element

  • C-c / element close
  • C-c C-e a select element content
  • C-c C-e b element beginning
  • C-c C-e c element clone
  • C-c C-e d child element (down)
  • C-c C-e e element end
  • C-c C-e i element insert
  • C-c C-e k element kill
  • C-c C-e n next element
  • C-c C-e p previous element
  • C-c C-e r rename element
  • C-c C-e s select element
  • C-c C-e u parent element (up)
  • C-c C-e v element vanish

HTML tag

  • C-c C-t a sort attributes
  • C-c C-t b tag beginning
  • C-c C-t e tag end
  • C-c C-t m fetch matching tag (also available for active blocks)
  • C-c C-t s select tag
  • C-c C-t p previous tag
  • C-c C-t n next tag

HTML attribute

  • C-c C-a b attribute beginning
  • C-c C-a e attribute end
  • C-c C-a i attribute insert
  • C-c C-a s attribute select
  • C-c C-a t attribute transpose
  • C-c C-a n attribute next

Helper functions

Engine families

Never forget to update the auto-mode-alist.
django twig, jinja, jinja2, erlydtl, swig, liquid, selmer (Clojure), clabango, swig *.djhtml, *twig*, *.dtl, *.tmpl
php *.php, *.psp, *.ctp php
erberuby, ember, erubis, embedded javascript*.erb, *.rhtml, *.ejs
velocitycheetah, vtl*.vsl, *.vtl, *.vm
gogtl*.gohtml, *.gotmpl
jsp*.jsp, *.gsp
aspx*.aspx, *.ascx
razorplay, play2*.cshtml, *.vbhtml
ctemplatemustache, handlebars, ember, hapax, ngtemplate, meteor, blaze*.hbs, *.mustache
template-toolkit*.tt, *.tt3



Dedicated google group : https://groups.google.com/d/forum/web-mode

To report a bug, prefer submitting an issue on GitHub (note: a screenshot, an example on gist and the output of M-x web-mode-debug are always useful).


2015-XX : current/devel
2014-10 : v10 aka “Cinque Terre” Release
2014-05: v9 aka “IRCAM” Release
2014-01: v8 aka “Copenhagen” Release
2013-09: v7 aka “Verteuil” Release
2013-06: v6 aka “Roma” Release
2013-03: v5 aka “Tignes” Release
2013-01: v4 aka “Trianon Palace” Release
  • compatibility with new engines: velocity/cheetah, smarty
  • compatibility with the alternative FreeMarker syntax: [# ] [@ ] (thx Daniel Dekany)
  • indentation improvement (thx gnuvince)
  • speed improvement when using web-mode-engines-alist
2012-12: v3.5 aka “St Petersbourg” Release
2012-11: v3 aka “Sandy at the Knickerbocker Club” Release
2012-09: v2 aka “La Baule” Release
2012-05: v1 aka “Valençay” Release
2011-08: v0 aka “La Ferté-Vidame” Release


Ivan Toshkov, Guillaume Pasquet, Andrei Chitu, Jose Peleteiro, Tad Fisher, Lee SanGu, Igor Shymko, Teruki Shigitani, Ed Slocomb, Adam Sokolnicki, Haijun Yang, Mitchel Humpherys, Brent Carmer, Bin Chen, Nate Eagleson, Matthew Carter


François-Xavier Bois - < fxbois AT Google Mail Service >

Co-founder and CTO of Kernix, Digital Agency (Web/Mobile) in Paris (FR).

@fxbois -

web-mode.el has been presented to the 7th European Lisp Symposium with paper Heterogeneous recursive code parsing with Emacs Lisp.

Friendly links: scopalto, magazines gratuits au format pdf, DBSE, ultimate recommendation engine