Formatting by Language

How to format HTML code on Mac

You can do this with Note My in one pass. Here is how to rewrite the nesting of markup that came from a template engine, a minifier or a paste — and how the parts of the page that must stay exactly as written are kept that way.

An HTML file goes ragged quickly. A template engine emits everything at column zero. A build step collapses the page onto four enormous lines. Someone pastes a component in at the wrong depth and nobody notices for a month. The markup is correct; it is simply unreadable, and reading it is the job you actually have.

Note My re-indents an HTML document in one pass on your Mac, with no toolchain to install. This guide covers what that pass rewrites, the four HTML-specific controls, what happens to <pre> and to the script and style blocks inside the page, and what else you can do with the file once it is open.

Note

Formatting happens on your Mac. Nothing is uploaded, there is no account, and an unreleased page never leaves the machine to be tidied up.

What the HTML pass rewrites

Re-indent does two jobs, and the name only describes the first.

The first is depth. Every line is placed at the level its nesting says it belongs to, using your indent width and your choice of tabs or spaces. The second is structural: our indentation engine unpacks statements that share a line, so markup squashed onto one line comes back opened out.

HTML is one of the fifteen languages our indentation engine supports, so a page comes back shaped the way markup should read. Your markup itself is left exactly as you wrote it: it renames no tags, reorders no attributes, and adds nothing. It changes where characters sit, subject to the controls below.

Open the Indentation sheet and choose HTML

Note

Everything starts in one place: the toolbar Indent button, the braces glyph towards the right. It opens the Indentation sheet, where you choose the language and set the shape of the pass before a single line moves.

  1. Open the file and check the language

    Open the page with ⌘O, or drag it from the Finder onto the tab bar. Our advanced language identifier settles the language as the file opens, so a page saved as .html is ready to work on.

    If the status bar does not show HTML, click the Identify pill there. The Language Inspector opens, reads "Identified programming language: X", and lets you override it and confirm.

  2. Save the file first

    Press ⌘S before anything else. A saved copy on disk is your dependable way back: File ▸ Reload from Disk (⌘R) drops the saved version straight into the tab, and reloading never changes the file on disk. Our auto-recovery safety net looks after your work through an unexpected quit as well.

  3. Press the Indent button

    It is the braces glyph, towards the right of the toolbar. It does not act immediately — it opens the Indentation sheet, and nothing in your document changes until you press Apply.

  4. Set the language picker to HTML

    The picker holds sixteen entries: a global default plus fifteen languages. Choosing HTML snaps the width and tabs-or-spaces controls to your stored HTML values and reveals the HTML section underneath.

  5. Set the width and the character

    Indent width defaults to 4 and the sheet accepts 1 to 12. Tabs or spaces defaults to spaces. Two is the usual choice for markup, for the reason in the next section — set it here and it is remembered for HTML specifically.

  6. Check the HTML controls, then Apply

    The four of them are covered below. When the sheet reads the way you want, press Apply. Cancel, or ⎋, changes nothing at all.

Tip

The preview card in the sheet renders a sample if <condition> { … } snippet at your current settings, so you can see what your width and your tabs-or-spaces choice look like before you commit them to the page.

Indent width for deeply nested markup

HTML nests harder than most code. A section inside a container inside a wrapper inside the body is four levels deep before you have written anything, and at a width of four that is sixteen columns of dead space on every line of real content. That is why most house styles land on two spaces for markup.

Indent width is stored per language, alongside brace style and tabs-or-spaces, so a width of 2 for HTML sits happily beside the width of 4 you use for Swift. Set it once with HTML chosen in the picker and every page you open afterwards is shaped at markup's own width, whatever you are working at in the rest of the project.

Once the file is indented, indentation guides make the depth legible. They are on by default, drawn as Dots, and there are ten styles in Settings ▸ Guides if dots are too faint against your theme.

The four HTML controls

The four HTML-specific controls in the Indentation sheet and what each one governs
ControlWhat it governs
<pre> preservation (on by default)Whether the contents of a preformatted block are left exactly as written while everything around them is re-indented.
Script and style formatting (on by default)Whether the JavaScript and CSS embedded in the page are formatted along with the markup, rather than skipped.
Attribute wrapWhether a long attribute list is broken across lines instead of being left on one.
Extra inline tagsA comma-separated list of additional tag names to treat as inline, so they are not opened onto lines of their own.

Keeping <pre> exactly as written is the one that matters most, and it is on by default. Whitespace inside a preformatted block is content: re-indent it and you have changed what the page renders. With preservation on, the block's own lines are left alone while the markup surrounding it is placed at the correct depth.

Script and style formatting is also on by default, so the CSS in a <style> block and the JavaScript in a <script> block are shaped rather than skipped. Turn it off if those blocks are generated and you would rather they came back untouched.

Attribute wrap and the extra inline tags list are the two you set deliberately. Reach for attribute wrap on a page built out of long utility-class lists, where one tag can run well past the width of the window, and leave it alone where the attributes are already short. The inline list is for the elements you would rather see sitting in the flow of a sentence than opened onto rows of their own: name them, separated by commas, and the pass keeps them where they read best.

One note on line length. Wrapping is something you ask for, so until you turn attribute wrap on, every line comes back exactly as long as you wrote it and only its depth has changed. That is what makes a pass safe to run on a page somebody else wrote. All four controls are remembered once you have set them, so the house style you settle on this afternoon is the shape every page you open afterwards comes back in.

Important

Brace style, indent width and tabs-or-spaces are remembered per language, so a width of 2 for HTML sits happily beside a width of 4 for Swift. The four HTML controls are remembered globally, so once you have set them the way you like, they hold for every page you open.

Closing tags as you type

Separate from re-indent, and worth knowing because it stops badly nested markup happening in the first place. With Smart Edit on, typing the > that ends an opening tag inserts the matching closing tag after the caret. The rules are specific:

  • It happens on the > that ends an opening tag, in any document set to HTML. Set the language with the status-bar Identify pill and tag completion comes with it.
  • The caret stays between the two tags. The closing tag lands after it, so you carry straight on typing the content with the element already closed behind you.
  • Closing and self-closing tags are rejected, so typing </div> or <img … /> does not produce a second closer.
  • Void elements are excluded — br, img, input, hr, meta, link, area, base, col, embed, param, source, track and wbr never get a closing tag they should not have.

Smart Edit has five switches — a master and one each for Return, brackets, quotes and tags — and all five are on by default. There are exactly six auto-pairs: (), [], {}, "", '' and backticks, and markup is looked after by the tag completion described above, which arrives at the >.

Making sure the page is set to HTML

Most of the time this is settled before you get to it. Our advanced language identifier picks the language up as the document opens, so a page saved as .html arrives as HTML: the colour is right, the HTML section of the Indentation sheet is one choice away, and tag completion is available. It happens on your Mac — nothing is sent anywhere, and there is no account behind it.

You are never stuck with the result. The status-bar Identify pill is always there, and the language you choose in it wins. That matters in two cases: a bare fragment pasted into an untitled tab, which can come up as Plain Text; and a page saved under some other extension. Set either one to HTML in the Inspector and every HTML behaviour follows — the colouring, the HTML section of the Indentation sheet, and tag completion as you type.

A template that mixes PHP and markup opens as PHP, which is usually what you want for the rest of the file. To have the page indented as HTML anyway, choose HTML in the sheet's language picker before you press Apply — that choice governs the pass.

What else you can do with the page

A format pass is one job among several, and the rest of the app is built around the same open file:

  • See exactly what moved. Duplicate the page in the Finder before you press Apply, then open both copies and read them side by side in our comparison view. The lines that shifted are laid out for you, which is the quickest way to satisfy yourself that only whitespace changed.
  • Change one attribute across the whole page. Our find and replace works over the open document, so a class name or an asset path that appears forty times is one operation rather than forty.
  • Start from a page that is already correct. index.html is one of the built-in documents in our template library, so a new file arrives with its structure in place and its language already settled.
  • Keep your comments as you wrote them. The wording inside an HTML comment comes back exactly as you typed it: the pass sets the line at the depth it belongs to and leaves what the comment says alone.
  • Open a page that is far too large to read. Our large-file engine keeps a minified page of several megabytes scrolling and editable — which, conveniently, is the file you most often want re-indented.
  • Handle the data files beside it. The Edit menu carries Format, Minify and Validate for JSON, and Format and Minify for XML, so a page's fixtures and feeds are covered in the same window.
  • Repeat a fiddly edit. Our macro recorder replays a sequence of edits you have already made by hand, which suits a repetitive tidy-up running the length of a long page.

Run the pass on the whole document: Apply shapes the entire page in one go, which is how a re-indent is normally used. The saved copy on disk stays exactly as it was until you save again, so File ▸ Reload from Disk (⌘R) will always bring back the version you started with.

Troubleshooting

The page came back looking the same

Two harmless cases. An empty document has nothing to re-indent. And a page already sitting at the width and character you asked for has nothing left to move, so a tidy file comes back exactly as it went in. Scroll to the most deeply nested section you have and read the depth there: if it lines up, the pass has already done its work. If you were expecting a change, check the sheet's language picker and the width before you look any further.

A very large page took a moment to come back

There is no size limit on what you can re-indent. On an ordinary page the tidied markup appears instantly. On a minified page of several megabytes — a built file, or a whole site's output sitting on four lines — give the window a moment to settle rather than pressing Apply a second time. Our large-file engine is what keeps a page that size open, scrolling and editable in the first place, so if you only need to read the thing you can leave it exactly as it is and still find your way around it.

The depth changes from a certain point downwards

Almost always an unclosed tag, or a stray brace inside an embedded script, and the result points straight at it: everything after the offending line sits a level too deep, so the first line at the wrong depth marks the spot. That makes a format pass a quick way of finding a tag you have lost track of in a long page. Note where the depth first goes astray, bring the saved file back with ⌘R, close the tag, and run the pass again — the second result reads correctly all the way down.

Getting back the markup you started with

Save with ⌘S before you press Apply and the way back is always one keystroke: File ▸ Reload from Disk (⌘R) drops the saved version straight into the tab, and reloading never changes the file on disk. That is the habit worth forming, because it lets you try a width, read the whole page at it, and reload if you would rather have the file as it was. Our auto-recovery safety net looks after the rest, including an unexpected quit with the page still unsaved.

Tags are not closing themselves as I type

Two things to check, both quick. First the language: tag completion follows the language the document is set to, so set it to HTML with the status-bar Identify pill and the behaviour comes with it. Second, Smart Edit: its master switch and its tag switch both need to be on, and both are on by default. With those in place, typing the > that ends an opening tag writes the closer for you and leaves the caret between the two, ready for the content.

My page has invisible characters in it

A literal non-breaking space pasted into markup looks exactly like a normal space and behaves differently. Turn on Show Invisibles in the toolbar to see them drawn — spaces as ·, tabs as →, a non-breaking space as a ring. That changes the drawing only. To remove them, use Clean ▸ Clean Invisible / Special Characters…: our hidden-character scanner shows what it has found and lets you apply only the fixes you choose.

Frequently asked questions

Where do I start a format pass on an HTML page?

In the toolbar. The Indent button — the braces glyph towards the right — is one click away from whatever you are reading, and it opens the Indentation sheet rather than acting immediately. That is where you set the language, the width and the four HTML controls, and where the preview card shows you the shape you have chosen before a single line of your page moves.

Will re-indenting break the way my page renders?

The pass changes whitespace and line structure, not markup. The place where whitespace is content is a preformatted block, and <pre> preservation is on by default precisely for that. If you have turned it off, turn it back on before formatting a page containing code samples.

Does it format the CSS and JavaScript inside the page?

Yes, by default. Script and style formatting is on, so embedded <script> and <style> content is shaped along with the markup. Switch it off in the sheet's HTML section if you would rather those blocks were left untouched.

How do I track down a tag I have forgotten to close?

Let the pass show you. Re-indent the page and read down the result: an unclosed tag leaves everything after it a level deeper than it belongs, so the first line at the wrong depth sits next to the tag at fault. Close it, run the pass again, and the depth reads correctly to the bottom of the file. For the data files beside your page, the Edit menu carries Validate for JSON.

How do I export my code as a styled HTML page?

Use File ▸ Export As ▸ HTML with Syntax Highlighting…. It writes a self-contained HTML file with an embedded stylesheet, so your syntax colouring survives the trip into a browser, a wiki or a review thread, and the page opens anywhere without anything else alongside it. There is no size limit on what you can export.

Is there a starting point for a new HTML file?

Yes. index.html is one of the built-in documents in our template library, reachable from File ▸ New from Template or the toolbar Templates pull-down. Starting there settles the language before you type.