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

Native Features


html php css js


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 and marmalade.

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 '("\\.jsp\\'" . 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))

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).

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

In summary, you may have to set both auto-mode-alist and web-mode-engines-alist.


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



  • C-c C-; 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 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 select element content (inner)
  • 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 u element vanish

HTML tag

  • 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

Helper functions

Engine families

Never forget to update the auto-mode-alist.
django twig, jinja, jinja2, erlydtl, swig, liquid *.djhtml, *twig*, *.dtl, *.tmpl
php *.php, *.psp, *.ctp php
erberuby, ember, erubis*.erb, *.rhtml
velocitycheetah, vtl*.vsl, *.vtl, *.vm
gogtl*.gohtml, *.gotmpl
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 and the output of M-x web-mode-debug are always useful).


2014-XX : current/devel
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



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

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

@fxbois -