How do I tidy up an HTML file's indentation in VI?

How do I fix the indentation of his huge html files which was all messed up?

I tried the usual "gg=G command, which is what I use to fix the indentation of code files. However, it didn't seem to work right on HTML files. It simply removed all the formatting.

I also tried setting :filetype = xml, to see if tricking it into thinking this was an XML file would help but it still didn't do it.


There's several things that all need to be in place. Just to summarize them all in one location:

Set the following option:

:filetype indent on
:set filetype=html           # abbrev -  :set ft=html
:set smartindent             # abbrev -  :set si

Then either move the cursor to the top of the file and indent to the end: gg =G
Or select the desired text to indent and hit = to indent it.


With filetype indent on inside my .vimrc, Vim indents HTML files quite nicely.

Simple example with a shiftwidth of 2:

<html>
  <body>
    <p>
    text
    </p>
  </body>
</html>

The main problem using the smart indentation is that if the XML (or HTML) sits on one line as it may end up coming back from a curl request then gg=G won't do the trick. Instead I have just experienced a good indentation using tidy directly called from VI:

:!tidy -mi -xml -wrap 0 %

This basically tells VI to call tidy to cleanup an XML file not wrapping the lines to make them fit on the default 68 characters wide lines. I processed a large 29MB XML file and it took 5 or 6 seconds. I guess for an HTML file the command should therefore be:

:!tidy -mi -html -wrap 0 %

As mentioned in comments, tidy is a basic tool which you could find on many base Linux / MacOS systems. Here is the projet's page in case you wish you had it but don't: HTML Tidy.


As tylerl explains above, set the following:

:filetype indent on
:set filetype=html
:set smartindent

However, note that in vim 7.4 the HTML tags html, head, body, and some others are not indented by default. This makes sense, as nearly all content in an HTML file falls under those tags. If you really want to, you can get those tags to be indented like so:

:let g:html_indent_inctags = "html,body,head,tbody" 

See "HTML indenting not working in compiled Vim 7.4, any ideas?" and "alternative html indent script" for more information.


This is my solution that works nicely for opening "ugly" HTML in a nicely spaced way:

vim fileIn.html -c "set sw=2 | %s/>/>\r/ | execute 'normal gg=G' | set nohlsearch | g/^\\s*\$/d"
  • The sw command is because my default is 4, which is too high for HTML.
  • The next part adds a newline (Vim thinks it's a carriage return, sigh) after each element (>).
  • Then re-indent the entire file with =.
  • Then unhighlight > (since I have set hlsearch in my vimrc).
  • Then remove all empty/whitespace-only lines (see "Vim delete blank lines" for more, also this is double-escaped because it's in the shell).

You can even add | wq! fileOut.html to the end if you don't want to enter Vim at all, but just clean up the file.