Consent

This site uses third party services that need your consent. Learn more

Skip to content

Blog

Writing content in Markdown

Headshot of Craig.

Craig Wright

In this article, I’m going to cover how to write content in Markdown, focusing specifically on standard Markdown plus a bit of GitHub Flavored Markdown for tables.

I won’t cover content reuse here, as that’s something that is going to vary depending on which Static Site Generator you use for publishing. My aim is to use Docusaurus for that, and I’ll try and cover it in a later post.

Right, let’s crack on with Markdown.


What is Markdown?

Markdown is a writing format that you write in plain text. You can create it in pretty much any text editor. It is a simple, human readable format that is widely familiar to developers.

Is it the best format for technical documentation? Arguably not, as other markup languages are more capable of providing the structures that we technical writers need. But Markup does have some advantages in that it is:

* Simple

* Lightweight

* Widely supported

* Already known or easy to learn for developers, engineers, and technical writers. 

* A good option for documentation that needs to be more collaborative.


Flavours of Markdown

There is not an official markdown standard. Instead, there are several different variations, which people often call "flavours". You can think of a flavour as a dialect that adds extra features. For example, standard Markdown does not support tables, but GitHub Flavour Markdown (GFM) does.

When you start on a project, you should find out what flavour of Markdown is currently being used. Also, find out what flavour your editor supports, because the editor’s preview may ignore Markdown that it doesn’t understand. Even if the preview appears incorrect, your Markdown should look fine when you publish.


What do you need to write in Markdown?

Not a lot! You can write it in any text editor that supports Markdown. I’ve been using the text editor in Visual Studio Code. Other than an editor, the only thing you need is to use the correct syntax for headings, paragraphs, lists, and other types of content.

StackEdit.io is an online editor that is free and supports many Markdown flavors.

Once you have your editor, you can create a new file in your local repo or open an existing one.


Create a new file

To create a new file using VS Code:

  1. Run VS Code.

  2. Select File and then Open folder and choose the folder where your docs live (your local repo).

  3. Expand your workspace in the Explorer sidebar and select the folder that is going to contain the new file.

    Note: If you don’t have any folders yet, you can add one by right-clicking in the Explorer sidebar and selecting New folder.

  4. Select File and then New File.

  5. Enter a file name, for example, Introduction, and then press Enter.

    New file creation in Visual Studio Code. The new file has been given the name Introduction and the Create new file (Introduction) Built-in option is selected automatically.
  6. Enter some Markdown into the file. To start with, try a hashtag followed by a space followed by the main heading text. For example:

    # Introduction
  7. Select File and then Save as.

    Note: If the Save as option is unavailable, click in the Explorer sidebar and then try again. Save and Save as are often unavailable if:

    • Your new file doesn't have content

    • Your new file is open in preview but you haven't made any changes yet.

    • The focus isn't in the editor. Selecting something else in the editor can move the focus.

  8. Set the Format for the new file to Markdown.

    Save as settings on Mac. Save As is for the filename, Tags is for MacOS tags, Where is for the location, and Format should be set to Markdown if that's the language you are using.

    If you don't have an option to select Markdown as the format, just make sure the filename has .md as the file extension. This signals that it is a Markdown file.

    The location for the file is automatically set to the folder you selected when you added the file. You can choose a different location if you prefer.

  9. Select Save.

If you are using a different editor, refer to the documentation to learn how to create a new file. Make sure you save it with a .md file extension.

When you have a file open in the editor, you can start editing the content using Markdown.


Edit an existing file

To edit an existing file in VSCode:

  1. Run VSCode.

  2. Select File and then Open folder and choose the folder where your docs live (your local repo).

  3. Navigate to the file in the Explorer sidebar and then double-click on the file to open it in the editor.

If you are using a different editor, refer to the documentation to learn how to browse your project and open a file.

When you have a file open in the editor, you can start editing the content using Markdown.


Headings

There are different ways of marking up headings. My preferred way is to add a hash tag followed by a space before the heading text for heading 1, two hashtags for heading 2 and so on. Each heading should be surrounded by blank lines.

# Heading 1

## Heading 2

### Heading 3

#### Heading 4

Another way is to add equals signs under the heading 1 text and dashes (hyphens) under the heading 2 text. It doesn't matter how many equals or dash characters you use, as long as you only add that character to the line and then press return. 

I can't see the point of using equals and dash when you have to use hashtags for levels 3 onwards anyway. Using hashtags for all heading levels is more consistent.

There are a maximum of 6 heading levels in Markdown. If you're getting beyond 4, there's possibly an issue with your content structure and you might want to rethink how it is organized.


Paragraphs

Press return twice to separate two paragraphs, like this:

This is paragraph 1. I am going to press return twice now ...

This is paragraph 2.

Line breaks

There are many ways of adding a line break, including:

  • Add two spaces at the end of the line followed by return.

  • Enter a backslash and then press return.

  • Include an HTML break tag <br />.

This is a line that is going to break with two spaces  
followed by return. I added the two spaces after the first use of "two spaces" in the paragraph.

Lists

Let's look at creating different types of list.

Unordered list (bullet list)

Start each line with an asterisk, plus symbol, or dash. Put a space after the character you used and then enter your text.

* list item 1
* list item 2
* list item 3

Nested unordered list

To create a nested unordered list, create the upper level list item and then add another line. Start that line with 2 spaces or 4 spaces and then add a new list item (using asterisk, plus symbol or dash).

* List item 1
* List item 2
  * List 2.1 Item 1
  * List 2.1 Item 2
* List item 3
* List item 4

Ordered list (number list)

Enter the number followed by a full stop and a space. You don't have to use correct numbering in Markdown as they will render in the correct order anyway. But it makes more sense to use the correct numbers in the first place, right?

1. List item 1

2. List item 2

3. List item 3

Nested ordered list

Start the upper level list and then, on the line for the next list item, add 2 or 4 spaces at the start.

1. First item
    1. Subitem 1
    2. Subitem 2
2. Second item

Mixing the bullet and number list styles

You can have bullet lists inside a numbered list and vice-versa. Again, just use 2 or 4 spaces to indent and then use the appropriate character for the list, such as an asterisk.

1. Step one

   * Item 1

   * Second detail

2. Step two

   * Another point

   * More info

Task lists (checkboxes)

These are only available if you use GitHub Flavored Markdown (GFM).

Enter a hyphen followed by a space and then square brackets for the checkboxes. After the square brackets, add a space and then the text for the box. To have a box checked by default, enter an X inside the square brackets.

- [x] Write docs
- [ ] Review PR
- [ ] Ship release

Result:

Three checkboxes. The first box is checked by default.


Images

The handling of images in plain markdown is limited. You can insert an image, but you can't control its size. If you need to control the size, use HTML <img> tags to insert the image in your markdown instead.

Note: If you're using MDX (like Docusaurus) you can use React image components for more control.

Here, I'm going to focus on plain markdown.

Inline images

To add an inline image:  

  1. Enter an exclamation mark followed by square brackets.

  2. Inside the square brackets, enter the alt text for the image.

  3. Add parentheses after the closing square bracket. Enter the address of the image inside the parentheses.

For example:

![Dumbell photo from Mika Baumeister on Unsplash](https://plus.unsplash.com/premium_photo-1671028546491-f70b21a32cc2?q=80&w=2070&auto=format&fit=crop&ixlib=rb-4.1.0&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D)

Referenced images

In Markdown, a referenced image is when you separate the image link definition from the place where you use it. They are useful if you want to insert the same image multiple times, as you can enter a label instead of the full URL each time.

For referenced images, you define a label and set its value to the URL of the image. Then, in your content, you enter the label wherever you want the image to appear.

To define the label, use this format:

[image label name]: URL "alt text"

For example:

[Dumbells]: https://plus.unsplash.com/premium_photo-1671028546491-f70b21a32cc2?q=80&w=2070&auto=format&fit=crop&ixlib=rb-4.1.0&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D "Dumbell photo from Mika Baumeister on Unsplash"

To insert the image in your content, add a reference to the image label using this format:

![Alt text][name of image label]

For example:

![Dumbell photo from Mika Baumeister on Unsplash][Dumbells]

The computer will:

1. Detect the image label reference in your text. 

2. Search in the label definitions at the bottom to find out what image to use. 

3. Insert the appropriate image at the points where that image label reference appears.

Controlling the size of images

In plain Markdown, there's no way to control the size. But as most Markdown engines support HTML, you can use that to control the size, for example:

<img src="url" alt="alt" width="400"/>

The width attribute in standard HTML only accepts widths in pixel values or numeric values. 

To get percentage widths, use inline CSS styles, like this:

<img src="url" alt="alt" style="width:60%;" />

Note: If you use HTML or CSS to add images, use those instead of the plain markdown references.


Code

There are two ways of including code in markdown:

* Inline code

* Code blocks

Note: It’s also possible to use syntax highlighting with code blocks, but only if it is supported by your Static Site Generator (SSG). 

Inline code

Inline code is content that appears in a monospace font with a shaded background on the same line as previous/following paragraph text. You use it to include a short snippet of code in a line of text in a paragraph. To make inline code, surround your code with backticks. 

For example:

<pre>Use the `cd` command to change the directory in Git.</pre> 

Result:

Use the cd command to change directory in Git.

Code blocks

Code blocks are multiple lines of code that are inset in a block, like an indented paragraph. For a code block:

  1. Enter three backticks on a new line.

  2. After the backticks, but on the same line, enter the name of the language being used, for example, Markdown.

  3. Enter your code on a new line.

  4. After the code, enter three backticks on a new line.

``` Markdown

This is a code block. It will display exactly as typed, with no colors or special formatting. for example: def hello(): print("Hello, world!") 

```

Typically, code blocks are used with syntax highlighting.

Syntax highlighting

Syntax highlighting adds colors and styles to code markup so that it easier to read and looks different to your regular text.

Plain markdown doesn't support syntax highlighting, but it is available in GitHub Flavored Markdown (GFM). You'll be able to use it as long as your static site generator (SSG) supports GFM (and most do).

To use syntax highlighting, add the name of the programming language directly after the three forward slashes. It should be on the same line as the forward slashes, like this:

```python
def greet():
    print("Hello, world!")
```
Syntax highlighting for python code. Def is blue, greet (): is white, print is green, "Hello, world!" is red inside white parenthesis.

Here is another example, this time using CSS:

```css

.red-flag {

  color: red;

  text-decoration: underline;

  text-decoration-color: black;

}

```
Syntax highlighting for CSS. .red flag is yellow, the attributes such as color and text-decoration are light blue, and the curly brackets and values are white.

To add links in Markdown, you can include inline links or reference links.

Most of the technical writers I asked said they prefer to use inline links. They don’t like having to scroll down to the bottom of the file to see the link target, which can often provide context. But the downside is that it can be more complicated to update the links at a later date, if needed.

Personally, I would choose one way and stick to it consistently. Mixing the two approaches seems like it could cause extra work later on. Consistency wins.

Inline links

Inline links are where you include the link text and the target URL in the body of your text.

Use square brackets for the text for the link. Use parenthesis for the URL.

[Google](https://www.google.com)

Result:

Text that reads: use a search engine, such as Google, to find your exact location. The word Google is a link.

You can also use angle brackets for website links and email links:

<https://www.straygoat.co.uk>
<craigwright@straygoat.co.uk>

Reference links

Reference links are a tidier way of including links in your Markdown. Rather than include the full URL for a page every time you link to it, you create a shorter alias (called a link label) that you use instead. Then, at the bottom of the file, you define what that link label references.

If you're familiar with variables, it's a similar concept — the label is like a variable name, and the full URL is the value.

To define the URL at the bottom of the file, use this syntax:

[link label]: URL

For example:

<!-- references -->
[docs]: https://www.somewebsite.com/docs

To reference the link in your text, use this syntax:

[link text][link label]

For example:

For more information, see the [documentation][docs].

Result:

Rendered text. It reads "For more information, see the documentation." The word documentation is a hyperlink to content elsewhere.

Defining link labels in a separate file

It's also possible to have the link label definitions in a separate file, rather than in the individual Markdown files. 

The concept is:

  1. You create your Markdown files and include links. Instead of defining the values for the link labels at the bottom of your Markdown files, you define them in a separate file. 

  2. Also in your Markdown files, include an instruction to tell your static site generator (SSG) to import the file that contains the link label definitions.

3. In a separate file, add the link labels and the addresses they should link to.

This approach can make it easier to manage links to scale, but it is not supported in Markdown. Rather, it is available in some SSGs, but not all. For this reason, I won't cover it here, but it’s good to be aware that it is possible.


Tables

Tables are not supported in plain Markdown, but they are included as an extension in GitHub Flavored Markdown (GFM). Most static site generators support or partially support GFM by default or via plugins and extensions.

Tables are basic in Markdown, so you may need to use HTML tables instead, see Limitations.

Limitations of tables in Markdown

Tables are very basic in Markdown.  There is support for:

✅ Header row

✅ Columns

✅ Rows

✅ Column alignment

But no support for:

❌ Formatting inside cells, such as bold

❌ Nested tables

❌ Spanning

❌ Merging

❌ Complex layouts

❌ Automatic wrapping or text overflow

❌ Sorting

❌ Filtering

❌ Links and images in cells

❌ Classes for styling with CSS/JS

If you need complex tables with features that are not supported in Markdown, you may be able to add them as HTML. But this depends on whether your Static Site Generator supports HTML tables.

Create a table in Markdown

The following sections explain how to add columns, rows and headers and set the column alignment. I'll include an example at the end.

Columns

Use the pipe character to | mark the start and end of a column.

|Column A|Column B|

Table headers

Use a line of dashes after the first row to mark that row as the table header.

|Column A|Column B|

|--------|--------|

Note: You also need the pipes to create the structure of the row.

Rows

Create each row on a new line.

| Column A | Column B |

|----------|----------|

|Row 1A    | Row 1B   |

|Row 2A    | Row 2B   |

Alignment

Use a colon at the left side of a column header cell to align the entire column to the left. Left-aligned is the default.

| Column 1 | Column 2 |

| :--------| ---------|

|Row 1A    | Row 1B   |

Column 1 is aligned to the left. So is Column 2, even though it does not have a colon. This is because left-alignment is the default for tables.

Use a colon at the right side of a column header cell to align the entire column to the right.

| Column 1 | Column 2 |

|----------|---------:|

|Row 1A    | Row 1B   |

Column 2 is aligned to the right, as its header cell has the colon on the right. Column 1 remains left-aligned as it does not have the colon on the right.

Use a colon at both sides of a column header cell to align the entire column centrally.

| Column 1 | Column 2 |

|:--------:|:--------:|

|Row 1A    | Row 1B   |

Both columns are aligned centrally as the header cells for Column 1 and Column 2 have colons on both ends.

Example table

Here is an example of a simple table with 3 columns and 6 rows. The first column is left aligned, the second column is centred, and the third column is right-aligned.

| Column 1 | Column 2 | Column 3 |

|:---------|:--------:|---------:|

| Row 1A   | Row 1B   | Row 1C   |

| Row 2A   | Row 2B   | Row 2C   |

| Row 3A   | Row 3B   | Row 3C   |

| Row 4A   | Row 4B   | Row 4C   |

| Row 5A   | Row 5B   | Row 5C   |

| Row 6A   | Row 6B   | Row 6C   |

Emphasis

Standard Markdown supports Italic and Bold as types of emphasis.

Italic

For italic text, use an asterisk * before and after the terms you want to emphasize. Alternatively, you can use an underscore before and after the terms _ but this may be more likely to cause issues later down the line, especially if you need to write about files that use underscores in their filenames.

Guess which word I'm going to make appear in *italicized* text?

I don't use italics very often as they can be difficult for some dyslexic people to read. The British Dyslexia Association states:

"Avoid underlining and italics as this can make the text appear to run together and cause crowding. Use bold for emphasis. (Dyslexia Style Guide 2022)."

The GOV.UK design system also states:

"Don't use italics, as this text can be difficult for dyslexic users to read".

Bold

Use double asterisk before and after the terms you want to emphasize. I'd commonly use this strong bold text for the names of options that users need to select.

1. Select Open.

2. Select Auto-render.

3. Select Save when the rendering is complete.

You can use double underscores instead of double asterisk.

Escape characters

If you want a character that is used for emphasis to appear in your text, you will need to "escape" it. Use the backslash character ( \ ) immediately before the character you want to keep. 

For example, you might have a sentence that contains underscores as part of a file name and you want those to be visible in the text, not used as emphasis. For that, you would put a backslash before the underscores, like this:

**start\_filename\_end**

This would produce start_filename_end emphasised in bold in the output.


Quotes

Use the right-facing angle bracket to mark a quote.

> "If you want the rainbow, you've got to put up with the rain'. Do you know which ‘philosopher’ said that? Dolly Parton." - David Brent, The Office

Use double space followed by return to add a line break inside a quote.


Horizontal rule

Add three or more consecutive dashes, asterisks, or underscores to get a horizontal rule. Spaces are allowed between the characters, if you prefer to use them.

******
The series of asterisks above turn into a horizontal rule when published (and will appear in HTML previews too).
A horizontal rule above some text in the HTML preview in Visual Studio Code.

Okay, that’s covered the basics of writing content in Markdown. In the next post, I’ll look at saving and committing and the various stages your content will go through.

Posted under Docs like code

Last modified: 30 August 2025

Headshot of Craig.

Craig Wright is an experienced technical writer based in Chesterfield, UK.  He hates writing about himself in the third person, so I shall stop now.

Always interested in new content writing opportunities. Remote working preferred.

Get in touch

Let’s talk about your project

I’m here to help and offer my expertise as a technical writer. Get in touch and let me know what you need.