diff --git a/src/editor.c b/src/editor.c
index 11c7737..2a473d2 100644
--- a/src/editor.c
+++ b/src/editor.c
@@ -1305,6 +1305,37 @@ static gint get_python_indent(ScintillaObject *sci, gint line)
 }
 
 
+static gint get_xml_indent(ScintillaObject *sci, gint line)
+{
+	gboolean need_close = FALSE;
+	gint end = sci_get_line_end_position(sci, line) - 1;
+
+	if (sci_get_char_at(sci, end) == '>' &&
+		sci_get_char_at(sci, end - 1) != '/')
+	{
+		gint style = sci_get_style_at(sci, end);
+
+		if (style == SCE_H_TAG || style == SCE_H_TAGUNKNOWN)
+		{
+			gint start = sci_get_position_from_line(sci, line);
+			gchar *line_contents = sci_get_contents_range(sci, start, end + 1);
+			gchar *opened_tag_name = utils_find_open_xml_tag(line_contents, end + 1 - start);
+
+			if (NZV(opened_tag_name))
+			{
+				need_close = TRUE;
+				if (sci_get_lexer(sci) == SCLEX_HTML && utils_is_short_html_tag(opened_tag_name))
+					need_close = FALSE;
+			}
+			g_free(line_contents);
+			g_free(opened_tag_name);
+		}
+	}
+
+	return need_close ? 1 : 0;
+}
+
+
 static gint get_indent_size_after_line(GeanyEditor *editor, gint line)
 {
 	ScintillaObject *sci = editor->sci;
@@ -1317,11 +1348,25 @@ static gint get_indent_size_after_line(GeanyEditor *editor, gint line)
 
 	if (iprefs->auto_indent_mode > GEANY_AUTOINDENT_BASIC)
 	{
+		gint additional_indent = 0;
+
 		if (lexer_has_braces(sci))
-			size += iprefs->width * get_brace_indent(sci, line);
+			additional_indent = iprefs->width * get_brace_indent(sci, line);
 		else
 		if (FILETYPE_ID(editor->document->file_type) == GEANY_FILETYPES_PYTHON)
-			size += iprefs->width * get_python_indent(sci, line);
+			additional_indent = iprefs->width * get_python_indent(sci, line);
+
+		/* HTML lexer "has braces" because of PHP and JavaScript.  If get_brace_indent() did not
+		 * recommend us to insert additional indent, we are probably not in PHP/JavaScript chunk and
+		 * should make the XML-related check */
+		if (additional_indent == 0 && (
+			FILETYPE_ID(editor->document->file_type) == GEANY_FILETYPES_HTML ||
+			FILETYPE_ID(editor->document->file_type) == GEANY_FILETYPES_XML))
+		{
+			size += iprefs->width * get_xml_indent(sci, line);
+		}
+
+		size += additional_indent;
 	}
 	return size;
 }
@@ -2620,7 +2665,7 @@ static gboolean handle_xml(GeanyEditor *editor, gint pos, gchar ch)
 {
 	ScintillaObject *sci = editor->sci;
 	gint lexer = sci_get_lexer(sci);
-	gint min, style;
+	gint min, size, style;
 	gchar *str_found, sel[512];
 	gboolean result = FALSE;
 
@@ -2652,19 +2697,12 @@ static gboolean handle_xml(GeanyEditor *editor, gint pos, gchar ch)
 		/* User typed something like "<br/>" */
 		return FALSE;
 
-	str_found = utils_find_open_xml_tag(sel, pos - min, (ch == '/'));
-
-	/* when found string is something like br, img or another short tag, quit */
-	if (utils_str_equal(str_found, "br")
-	 || utils_str_equal(str_found, "hr")
-	 || utils_str_equal(str_found, "img")
-	 || utils_str_equal(str_found, "base")
-	 || utils_str_equal(str_found, "basefont")	/* < or not < */
-	 || utils_str_equal(str_found, "frame")
-	 || utils_str_equal(str_found, "input")
-	 || utils_str_equal(str_found, "link")
-	 || utils_str_equal(str_found, "area")
-	 || utils_str_equal(str_found, "meta"))
+	size = pos - min;
+	if (ch == '/')
+		size -= 2; /* skip </ */
+	str_found = utils_find_open_xml_tag(sel, size);
+
+	if (lexer == SCLEX_HTML && utils_is_short_html_tag(str_found))
 	{
 		/* ignore tag */
 	}
diff --git a/src/utils.c b/src/utils.c
index 27dbe5d..3c00f3c 100644
--- a/src/utils.c
+++ b/src/utils.c
@@ -281,7 +281,7 @@ gint utils_write_file(const gchar *filename, const gchar *text)
  * Search backward through size bytes looking for a '<', then return the tag, if any.
  * @return The tag name
  */
-gchar *utils_find_open_xml_tag(const gchar sel[], gint size, gboolean check_tag)
+gchar *utils_find_open_xml_tag(const gchar sel[], gint size)
 {
 	const gchar *begin, *cur;
 
@@ -290,10 +290,7 @@ gchar *utils_find_open_xml_tag(const gchar sel[], gint size, gboolean check_tag)
 		return NULL;
 	}
 	begin = &sel[0];
-	if (check_tag)
-		cur = &sel[size - 3];
-	else
-		cur = &sel[size - 1];
+	cur = &sel[size-1];
 
 	/* Skip to the character before the closing brace */
 	while (cur > begin)
@@ -312,16 +309,18 @@ gchar *utils_find_open_xml_tag(const gchar sel[], gint size, gboolean check_tag)
 	{
 		if (*cur == '<')
 			break;
-		else if (! check_tag && *cur == '>')
-			break;
 		--cur;
 	}
 
 	if (*cur == '<')
 	{
-		GString *result = g_string_sized_new(64);
+		GString *result;
 
 		cur++;
+		if (*cur == '/')
+			return NULL; /* we found a closing tag */
+
+		result = g_string_sized_new(64);
 		while (strchr(":_-.", *cur) || isalnum(*cur))
 		{
 			g_string_append_c(result, *cur);
@@ -334,6 +333,22 @@ gchar *utils_find_open_xml_tag(const gchar sel[], gint size, gboolean check_tag)
 }
 
 
+/* Returns true if specified tag doesn't usually contain any content and can be left unclosed */
+gboolean utils_is_short_html_tag(const gchar *tag_name)
+{
+	return utils_str_equal(tag_name, "br")
+	 || utils_str_equal(tag_name, "hr")
+	 || utils_str_equal(tag_name, "img")
+	 || utils_str_equal(tag_name, "base")
+	 || utils_str_equal(tag_name, "basefont")	/* < or not < */
+	 || utils_str_equal(tag_name, "frame")
+	 || utils_str_equal(tag_name, "input")
+	 || utils_str_equal(tag_name, "link")
+	 || utils_str_equal(tag_name, "area")
+	 || utils_str_equal(tag_name, "meta");
+}
+
+
 const gchar *utils_get_eol_name(gint eol_mode)
 {
 	switch (eol_mode)
@@ -2034,5 +2049,3 @@ gchar **utils_copy_environment(const gchar **exclude_vars, const gchar *first_va
 
 	return result;
 }
-
-
diff --git a/src/utils.h b/src/utils.h
index 1303fea..5e23f98 100644
--- a/src/utils.h
+++ b/src/utils.h
@@ -136,7 +136,9 @@ gboolean utils_is_opening_brace(gchar c, gboolean include_angles);
 
 gint utils_write_file(const gchar *filename, const gchar *text);
 
-gchar *utils_find_open_xml_tag(const gchar sel[], gint size, gboolean check_tag);
+gchar *utils_find_open_xml_tag(const gchar sel[], gint size);
+
+gboolean utils_is_short_html_tag(const gchar *tag_name);
 
 void utils_ensure_same_eol_characters(GString *template, gint target_eol_mode);
 
