web-mode.el

About 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). is an autonomousmajor-mode for editingHTML documents can embed parts (CSS / JavaScript) and blocks (client / server side).

Support You can help web-mode.el by donating on You can help web-mode.el by donating on or by sponsoring on

Native Features smart indentation (according to the context : HTML, code, JavaScript or CSS)

(according to the context : HTML, code, JavaScript or CSS) compatibility with many template engines : php, jsp, gsp (grails), asp / asp.net ajax (atlas), django / twig / jinja(2) / erlydtl (zotonic) / selmer, erb, ejs, freemarker, velocity, cheetah, smarty, ctemplate / mustache / hapax / handlebars / meteor / blaze / ember.js / velvet, blade (laravel), knockoutjs, go template (revel), razor/play, dust, closure (soy), underscore.js, template-toolkit, liquid (jekyll), angular.js, web2py, mako (pylons), reactjs (jsx), mojolicious, elixir (erlang), thymeleaf, cl-emb, heist, archibus, xoops, hero, spip, svelte, elixir

: php, jsp, gsp (grails), asp / asp.net ajax (atlas), django / twig / jinja(2) / erlydtl (zotonic) / selmer, erb, ejs, freemarker, velocity, cheetah, smarty, ctemplate / mustache / hapax / handlebars / meteor / blaze / ember.js / velvet, blade (laravel), knockoutjs, go template (revel), razor/play, dust, closure (soy), underscore.js, template-toolkit, liquid (jekyll), angular.js, web2py, mako (pylons), reactjs (jsx), mojolicious, elixir (erlang), thymeleaf, cl-emb, heist, archibus, xoops, hero, spip, svelte, elixir jumping C-c C-n between opening / closing HTML tags (e.g. <div> and </div> ) or between opening / closing control blocks (e.g. <?php if (): ?> … <?php endif; ?> , <c:if> … </c:if> , {% for %} … {% endfor %} , {{#SECTION}} … {{/SECTION}} , etc.)

between opening / closing HTML tags (e.g. and ) or between opening / closing control blocks (e.g. , , , , etc.) dom navigation parent, child, traversal, beginning/end

parent, child, traversal, beginning/end code folding C-c C-f for HTML elements and control blocks

for HTML elements and control blocks HTML tag auto closing ( <div></ → <div>|</div> ), auto opening ( <div> RET </div> → ( <div>

··|

</div> ), auto expanding ( d/ s/ → <div><span>|</span></div> ), attribute auto quoting ( style= → style="|" )

( → ), ( → ( ), ( → ), attribute ( → ) syntax highlighting , according to the type of part/block

, according to the type of part/block snippet insertion C-c C-s (auto indented, aware of text selection, engine specific)

insertion (auto indented, aware of text selection, engine specific) auto pairing (e.g. <?p … hp ?> , {% … %} )

(e.g. … , … ) comment / uncomment M-; according to the type of block

according to the type of block clever selection and expansion C-c C-m

and css color fontification

suspicious whitespaces detection C-c C-w

detection clever understanding of comments and strings : a quote in the content of an html element doesn't "corrupt" the fontification, PHP heredoc strings compatibility, variable fontification in strings (only double ones quoted for PHP) , a part (javascript/css) can contain a string that embeds a block (e.g. php) that also contains strings, etc.

: a quote in the content of an html element doesn't "corrupt" the fontification, PHP heredoc strings compatibility, variable fontification in strings (only double ones quoted for PHP) , a part (javascript/css) can contain a string that embeds a block (e.g. php) that also contains strings, etc. html goodies nice handling of html attributes (no values, unquoted values, double/single quoted values), detection of void elements, compatibility with <script type="text/html"> , <script type="text/jsx"> , <script type="application/ld+json"> , <style lang="stylus"> , HTML entities substitution, tag mismatch detection, no indentation inside <pre> or <code> elements

nice handling of html attributes (no values, unquoted values, double/single quoted values), detection of void elements, compatibility with , , , , HTML entities substitution, tag mismatch detection, no indentation inside or elements many helpers : dom normalization, element renaming / transposal, attributes sorting, etc.

: dom normalization, element renaming / transposal, attributes sorting, etc. current HTML element highlighting , element content and tag customized fontification , current indentation column highlighting

, element , current highlighting filling M-q compatibility (for comments and HTML text)

Screenshot (prefer HD Quality) YouTube (prefer HD Quality)

Terminology In an HTML document, a part is interpreted by the navigator (e.g. a JavaScript part or a CSS part).

is interpreted by the navigator (e.g. a JavaScript part or a CSS part). A block is processed (client-side or server-side) before being rendered by the navigator (e.g. a PHP block, an Erb block, a dustjs block etc.). As a result, a block can be located in a part that is embedded in an HTML document. As a result, a block can be located in a part that is embedded in an HTML document.

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

Associate a content type web-mode.el can deal with many content types: html, xml, javascript, jsx, json, css. This was needed to edit *.js.erb files for example: js files that embed ruby blocks. Sometimes, web-mode.el can not guess the content type with the file extension.

e.g. you want to associate *.api files with web-mode. The var web-mode-content-types-alist can be used to associate a file path with a content type (add-to-list 'auto-mode-alist '("\\.api\\'" . web-mode)) (add-to-list 'auto-mode-alist '("/some/react/path/.*\\.js[x]?\\'" . web-mode)) (setq web-mode-content-types-alist '(("json" . "/some/path/.*\\.api\\'") ("xml" . "/other/path/.*\\.api\\'") ("jsx" . "/some/react/path/.*\\.js[x]?\\'")))

Customisation 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) Indentation HTML element offset indentation (setq web-mode-markup-indent-offset 2) CSS offset indentation (setq web-mode-css-indent-offset 2) Script/code offset indentation (for JavaScript, Java, PHP, Ruby, Go, VBScript, Python, etc.) (setq web-mode-code-indent-offset 2) By default, tag attributes are indented like this: <img src="pix.png" class="noborder"/> You can force a fixed indentation with web-mode-attr-indent-offset <img src="pix.png" class="noborder"/> web-mode inherits from 'standard-indent when this var is bound.



You can disable arguments|concatenation|calls lineup with (add-to-list 'web-mode-indentation-params '("lineup-args" . nil)) (add-to-list 'web-mode-indentation-params '("lineup-calls" . nil)) (add-to-list 'web-mode-indentation-params '("lineup-concats" . nil)) (add-to-list 'web-mode-indentation-params '("lineup-ternary" . nil))

HTML element offset indentation CSS offset indentation Script/code offset indentation (for JavaScript, Java, PHP, Ruby, Go, VBScript, Python, etc.) By default, tag attributes are indented like this: You can force a fixed indentation with web-mode inherits from when this var is bound. You can disable arguments|concatenation|calls lineup with Left padding For <style> parts (setq web-mode-style-padding 1) For <script> parts (setq web-mode-script-padding 1) For multi-line blocks (setq web-mode-block-padding 0)

For parts For parts For multi-line blocks Comments You can choose to comment with server comment instead of client (HTML/CSS/Js) comment with (setq web-mode-comment-style 2)

You can choose to comment with server comment instead of client (HTML/CSS/Js) comment with Syntax Highlighting Change face color (set-face-attribute 'web-mode-css-rule-face nil :foreground "Pink3") Available faces:

effects web-mode-folded-face, web-mode-warning-face, web-mode-whitespace-face, web-mode-html-entity-face (with web-mode-enable-html-entities-fontification), web-mode-comment-keyword-face html web-mode-doctype-face, web-mode-html-tag-face, web-mode-html-tag-bracket-face, web-mode-html-attr-name-face, web-mode-html-attr-value-face, web-mode-html-attr-equal-face, web-mode-html-tag-namespaced-face, web-mode-html-tag-custom-face, web-mode-attr-tag-custom-face json web-mode-json-key-face, web-mode-json-context-face, web-mode-json-string-face css web-mode-css-at-rule-face, web-mode-css-property-name-face, web-mode-css-function-face, web-mode-css-priority-face, web-mode-css-pseudo-class-face, web-mode-css-selector-face, web-mode-css-string-face code web-mode-builtin-face, web-mode-comment-face, web-mode-constant-face, web-mode-filter-face, web-mode-function-call-face, web-mode-function-name-face, web-mode-keyword-face, web-mode-preprocessor-face, web-mode-string-face, web-mode-symbol-face, web-mode-type-face, web-mode-variable-name-face block web-mode-block-control-face, web-mode-block-delimiter-face, web-mode-block-face (see web-mode-enable-block-face), web-mode-block-string-face, web-mode-block-comment-face part web-mode-part-face (see web-mode-enable-part-face), web-mode-script-face, web-mode-style-face, web-mode-part-string-face, web-mode-part-comment-face, web-mode-javascript-string-face content fontification web-mode-bold-face, web-mode-italic-face, web-mode-underline-face other web-mode-annotation-tag-face web-mode-annotation-type-face

Change face color Available faces: Shortcuts Change the shortcut for element navigation (define-key web-mode-map (kbd "C-n") 'web-mode-tag-match)

Change the shortcut for element navigation Snippets Add a snippet (setq web-mode-extra-snippets '(("erb" . (("toto" . "



"))) ("php" . (("dowhile" . "<?php do { ?>



<?php } while (|); ?>") ("debug" . "<?php error_log(__LINE__); ?>"))) )) The character | is used to locate the cursor position (this is optional)

Add a snippet The character is used to locate the cursor position (this is optional) Auto-pairs Add auto-pair (setq web-mode-extra-auto-pairs '(("erb" . (("beg" "end"))) ("php" . (("beg" "end") ("beg" "end"))) ))

Add auto-pair Enable / disable features Auto-pairing (setq web-mode-enable-auto-pairing t) CSS colorization (setq web-mode-enable-css-colorization t) Block face: can be used to set blocks background and default foreground (see web-mode-block-face ) (setq web-mode-enable-block-face t) Part face: can be used to set parts background and default foreground (see web-mode-script-face and web-mode-style-face which inheritate from web-mode-part-face ) (setq web-mode-enable-part-face t) Comment keywords (see web-mode-comment-keyword-face ) (setq web-mode-enable-comment-interpolation t) Heredoc (cf. PHP strings) fontification (when the identifier is <<<EOTHTML or <<<EOTJAVASCRIPT ) (setq web-mode-enable-heredoc-fontification t) The customisations below should not be put in the hook. Declare them before loading web-mode.el Keywords / Constants Add constants (setq web-mode-extra-constants '(("php" . ("CONS1" "CONS2"))) Also available: web-mode-extra-keywords , web-mode-extra-types



Add constants Also available: , Current element / column highlight Highlight current HTML element (see web-mode-current-element-highlight-face ) (setq web-mode-enable-current-element-highlight t) You can also highlight the current column with (setq web-mode-enable-current-column-highlight t)

Highlight current HTML element (see ) You can also highlight the current column with Context-aware auto-completion If you have auto-complete installed, you can set up per-language ac-sources with web-mode-ac-sources-alist: (setq web-mode-ac-sources-alist '(("css" . (ac-source-css-property)) ("html" . (ac-source-words-in-buffer ac-source-abbrev)))) To find a language's name, run the function web-mode-language-at-pos while in a block of it. All hooks in web-mode-before-auto-complete-hooks are run just before auto-completion starts. This is useful for adapting ac-sources meant for a single language to web-mode, like ac-source-yasnippet. Here is a sample config for editing PHP templates, using php-auto-yasnippets, emmet-mode, and ac-emmet: (setq web-mode-ac-sources-alist '(("php" . (ac-source-yasnippet ac-source-php-auto-yasnippets)) ("html" . (ac-source-emmet-html-aliases ac-source-emmet-html-snippets)) ("css" . (ac-source-css-property ac-source-emmet-css-snippets)))) (add-hook 'web-mode-before-auto-complete-hooks '(lambda () (let ((web-mode-cur-language (web-mode-language-at-pos))) (if (string= web-mode-cur-language "php") (yas-activate-extra-mode 'php-mode) (yas-deactivate-extra-mode 'php-mode)) (if (string= web-mode-cur-language "css") (setq emmet-use-css-transform t) (setq emmet-use-css-transform nil))))) The first customisations can be put in a hook like thisThe customisations below should not be put in the hook. Declare them before loading web-mode.el

Shortcuts General M-; comment / uncomment line(s)

comment / uncomment line(s) C-c C-f toggle folding on a tag/block

toggle folding on a tag/block C-c C-i indent entire buffer

indent entire buffer C-c C-m mark and expand

mark and expand C-c C-s insert snippet

insert snippet C-c C-w toggle display of invalid whitespaces DOM C-c C-d a replace apostrophes

replace apostrophes C-c C-d d show tag mismatch

show tag mismatch C-c C-d e replace HTML entities

replace HTML entities C-c C-d n normalize

normalize C-c C-d q replace dumb quotes

replace dumb quotes C-c C-d t traverse dom tree

traverse dom tree C-c C-d x xpath Block C-c C-b b block beginning

block beginning C-c C-b c block close

block close C-c C-b e block end

block end C-c C-b k block kill

block kill C-c C-b n next block

next block C-c C-b p previous block

previous block C-c C-b s block select HTML element C-c C-e / element close

element close C-c C-e a select element content

select element content C-c C-e b element beginning

element beginning C-c C-e c element clone

element clone C-c C-e d child element (down)

child element (down) C-c C-e e element end

element end C-c C-e f toggle folding on children

toggle folding on children C-c C-e i element insert

element insert C-c C-e k element kill

element kill C-c C-e m mute blanks between children

mute blanks between children C-c C-e n next element

next element C-c C-e p previous element

previous element C-c C-e r rename element

rename element C-c C-e s select element

select element C-c C-e t transpose element

transpose element C-c C-e u parent element (up)

parent element (up) C-c C-e v element vanish

element vanish C-c C-e w wrap element HTML tag C-c C-t a sort attributes

sort attributes C-c C-t b tag beginning

tag beginning C-c C-t e tag end

tag end C-c C-t m fetch matching tag

fetch matching tag C-c C-t n next tag

next tag C-c C-t p previous tag

previous tag C-c C-t s select tag HTML attribute C-c C-a b attribute beginning

attribute beginning C-c C-a e attribute end

attribute end C-c C-a i attribute insert

attribute insert C-c C-a k attribute kill

attribute kill C-c C-a n attribute next

attribute next C-c C-a p attribute previous

attribute previous C-c C-a s attribute select

attribute select C-c C-a t attribute transpose

Helper functions web-mode-apostrophes-replace : replace ' by ’ (only in HTML content)

: replace ' by ’ (only in HTML content) web-mode-entities-replace : replace html entities (only in HTML content)

: replace html entities (only in HTML content) web-mode-quotes-replace : replace dumb quotes (only in HTML content)

Engine families Never forget to update the Never forget to update the auto-mode-alist . name cousins extensions example django twig, jinja, erlydtl, swig, liquid, selmer (Clojure), clabango, swig, nunjucks *.djhtml, *twig*, *.dtl, *.tmpl, *.njk php *.php, *.psp, *.ctp erb eruby, ember, erubis, embedded javascript *.erb, *.rhtml, *.ejs velocity cheetah, vtl *.vsl, *.vtl, *.vm blade laravel *blade* go gtl *.gohtml, *.gotmpl jsp *.jsp, *.gsp freemarker *.ftl aspx *.aspx, *.ascx asp *.asp razor play, play2 *.cshtml, *.vbhtml ctemplate mustache, handlebars, ember, hapax, ngtemplate, meteor, blaze, velvet *.hbs, *.mustache smarty *.tpl dust *.dust closure *.soy underscorejs template-toolkit *.tt, *.tt3 mako *.mako lsp *.lsp

FAQ Autoremove final white spaces on save Add those lines in the web-mode hook (add-hook 'local-write-file-hooks (lambda () (delete-trailing-whitespace) nil))

Add those lines in the web-mode hook Make this mode faster M-x byte-compile-file

Platforms/Compatibility Tested on GNU/Linux, OSX and Windows.

Tested with versions 24 and 23 (some users seem to use web-mode.el with emacs 22).



Tested on GNU/Linux, OSX and Windows. Tested with versions 24 and 23 (some users seem to use web-mode.el with emacs 22). I want to use both php-mode and web-mode You can do it this way (add-to-list 'auto-mode-alist '("\\.php\\'" . php-mode)) (add-to-list 'auto-mode-alist '("\\.blade\\.php\\'" . web-mode)) Never forget that the matching is done on the path and not just on the filename. If your templates are stored in a subdirectory called views , html or templates , you can use such a configuration line: (add-to-list 'auto-mode-alist '("/\\(views\\|html\\|templates\\)/.*\\.php\\'" . web-mode))

You can do it this way Never forget that the matching is done on the path and not just on the filename. If your templates are stored in a subdirectory called , or , you can use such a configuration line: How can I turn auto indentation on ? Put this line in the web-mode-hook (local-set-key (kbd "RET") 'newline-and-indent) You can also use M-x electric-indent-mode .

Please note that starting with 24.4, Emacs does this by default.

Put this line in the web-mode-hook You can also use . Please note that starting with 24.4, Emacs does this by default. I want to use smartparens (defun my-web-mode-hook () (setq web-mode-enable-auto-pairing nil)) (add-hook 'web-mode-hook 'my-web-mode-hook) (defun sp-web-mode-is-code-context (id action context) (and (eq action 'insert) (not (or (get-text-property (point) 'part-side) (get-text-property (point) 'block-side))))) (sp-local-pair 'web-mode " Special thanks to Johan Ekenberg for this tip.

Can I contribute ? Of course! You can send bug reports/fixes, feature requests, etc.

You can also donate with the button located in the right column.

Special thanks to the generous donors: Ed Singleton, Laurence Bois, Daniel Parnell, Digital Strategies, Lars Hartmann, Christian Kruse, Johan Ekenberg, LE Sarvell KB, Clint Howarth, Kardakov Slava, Jason Steven Cornez, Pierre-Emmanuel Bois, Grant Rettke, Varun Madiath, Eric Newhuis, Argentov Pavel, Martin Gregory, Joshua Branson, David Sveningssonn, Hemant Kumar, LE Sarvell KB, Klaus Madsen, Kristian Nybo, Erik Nordlund, Dustin Paluch, Rodrigo García Suárez, Michael Craig, Alexandr Klizhentas, William Lindley, Ian Wilson, William Morton, Rachel Bingham, Simen Heggestøyl, Ruben Maher, Sunil Williams, Aleksey Koval, Steven Litvintchouk, Basharat Ahmad, Matthias Cords, Jakub Jankiewicz, Darren Embry, Jerome Truong, Manuel Kaufmann, Daniel Temple, Jonathan Soifer, Mikhail Pomaznoy, Mitchel Humpherys, Teo Klestrup Röijezon, Kaushal Modi, Yu-Chiang Hsu, Jun Hyunje, Hemal Pandya, Tomasz Ostaszewski, Sheldon McGrandle, Anirvan Chatterjee, Sébastien Feugère, Jonathan, Christopher Loubert, Mark VanZorn, Dangerous Interactive Systems

Of course! You can send bug reports/fixes, feature requests, etc. You can also donate with the button located in the right column. Special thanks to the generous donors: Ed Singleton, Laurence Bois, Daniel Parnell, Digital Strategies, Lars Hartmann, Christian Kruse, Johan Ekenberg, LE Sarvell KB, Clint Howarth, Kardakov Slava, Jason Steven Cornez, Pierre-Emmanuel Bois, Grant Rettke, Varun Madiath, Eric Newhuis, Argentov Pavel, Martin Gregory, Joshua Branson, David Sveningssonn, Hemant Kumar, LE Sarvell KB, Klaus Madsen, Kristian Nybo, Erik Nordlund, Dustin Paluch, Rodrigo García Suárez, Michael Craig, Alexandr Klizhentas, William Lindley, Ian Wilson, William Morton, Rachel Bingham, Simen Heggestøyl, Ruben Maher, Sunil Williams, Aleksey Koval, Steven Litvintchouk, Basharat Ahmad, Matthias Cords, Jakub Jankiewicz, Darren Embry, Jerome Truong, Manuel Kaufmann, Daniel Temple, Jonathan Soifer, Mikhail Pomaznoy, Mitchel Humpherys, Teo Klestrup Röijezon, Kaushal Modi, Yu-Chiang Hsu, Jun Hyunje, Hemal Pandya, Tomasz Ostaszewski, Sheldon McGrandle, Anirvan Chatterjee, Sébastien Feugère, Jonathan, Christopher Loubert, Mark VanZorn, Dangerous Interactive Systems Indentation behaves oddly (whitespace/TAB mixup, *-offset vars ignored) If you don’t want tabs, add (setq-default indent-tabs-mode nil) in your .emacs

If you want to indent only with tabs, use: (setq indent-tabs-mode t) . Moreover you might need to call (web-mode-use-tabs) in your web-mode hook.

TAB width can be set this way: (setq-default tab-width 4)

If you don’t want tabs, add in your .emacs If you want to indent only with tabs, use: . Moreover you might need to call in your web-mode hook. TAB width can be set this way: Syntax coloring does not work Some users might report issues when using themes that not play nicely with web-mode.

Before reporting a bug about highlighting, try a theme (e.g. Solarized).

Tips: when using emacs in a terminal, always try to enable 256 colors compatibility (xterm-256color).

If you consider that the color of HTML tags too light, you can customize faces like web-mode-html-tag-face or web-mode-html-attr-face .

Some users might report issues when using themes that not play nicely with web-mode. Before reporting a bug about highlighting, try a theme (e.g. Solarized). Tips: when using emacs in a terminal, always try to enable 256 colors compatibility (xterm-256color). If you consider that the color of HTML tags too light, you can customize faces like or . Autopairing, tag autoclosing does not trigger This is the normal behavior when you run emacs in a terminal (tty). That’s because in text mode, pasting a long text is like inserting it one character at a time. Thus, the consequences can be bad e.g. many auto closing/pairing instead of one. If you wan’t to force autoclosing, autopairing even in a terminal, add (setq web-mode-enable-auto-closing t) and (setq web-mode-enable-auto-pairing t) in your .emacs

(same approach for web-mode-enable-auto-indentation , web-mode-enable-auto-opening , web-mode-enable-auto-quoting )

Support To report a bug, submit an issue on GitHub (note: a screenshot, an example on gist and the output of M-x web-mode-debug are always useful). It may also be a good idea to look at the *Messages* buffer. For general questions (install, config, etc), use emacs.stackexchange.com (do not forget to associate the web-mode tag).