diff --git a/ale_linters/html/stylelint.vim b/ale_linters/html/stylelint.vim
new file mode 100644
index 00000000..908c4b02
--- /dev/null
+++ b/ale_linters/html/stylelint.vim
@@ -0,0 +1,27 @@
+" Author: Filipe Kiss http://github.com/filipekiss
+
+call ale#Set('html_stylelint_executable', 'stylelint')
+call ale#Set('html_stylelint_options', '')
+call ale#Set('html_stylelint_use_global', 0)
+
+function! ale_linters#html#stylelint#GetExecutable(buffer) abort
+ return ale#node#FindExecutable(a:buffer, 'html_stylelint', [
+ \ 'node_modules/.bin/stylelint',
+ \])
+endfunction
+
+function! ale_linters#html#stylelint#GetCommand(buffer) abort
+ let l:executable = ale_linters#html#stylelint#GetExecutable(a:buffer)
+ let l:options = ale#Var(a:buffer, 'html_stylelint_options')
+
+ return ale#Escape(l:executable)
+ \ . (!empty(l:options) ? ' ' . l:options : '')
+ \ . ' --stdin-filename %s'
+endfunction
+
+call ale#linter#Define('html', {
+\ 'name': 'stylelint',
+\ 'executable_callback': 'ale_linters#html#stylelint#GetExecutable',
+\ 'command_callback': 'ale_linters#html#stylelint#GetCommand',
+\ 'callback': 'ale#handlers#css#HandleStyleLintFormat',
+\})
diff --git a/doc/ale-html.txt b/doc/ale-html.txt
index 98fddc58..0f93f5cd 100644
--- a/doc/ale-html.txt
+++ b/doc/ale-html.txt
@@ -84,6 +84,31 @@ write-good *ale-html-write-good*
See |ale-write-good-options|
+===============================================================================
+stylelint *ale-html-stylelint*
+
+g:ale_html_stylelint_executable *g:ale_html_stylelint_executable*
+ *b:ale_html_stylelint_executable*
+ Type: |String|
+ Default: `'stylelint'`
+
+ See |ale-integrations-local-executables|
+
+
+g:ale_html_stylelint_options *g:ale_html_stylelint_options*
+ *b:ale_html_stylelint_options*
+ Type: |String|
+ Default: `''`
+
+ This variable can be set to pass additional options to stylelint.
+
+
+g:ale_html_stylelint_use_global *g:ale_html_stylelint_use_global*
+ *b:ale_html_stylelint_use_global*
+ Type: |String|
+ Default: `0`
+
+ See |ale-integrations-local-executables|
===============================================================================
vim:tw=78:ts=2:sts=2:sw=2:ft=help:norl:
diff --git a/doc/ale.txt b/doc/ale.txt
index 2a78a9de..8713a430 100644
--- a/doc/ale.txt
+++ b/doc/ale.txt
@@ -119,6 +119,7 @@ CONTENTS *ale-contents*
htmlhint............................|ale-html-htmlhint|
tidy................................|ale-html-tidy|
write-good..........................|ale-html-write-good|
+ stylelint...........................|ale-html-stylelint|
idris.................................|ale-idris-options|
idris...............................|ale-idris-idris|
java..................................|ale-java-options|
diff --git a/test/command_callback/test_html_stylelint_command_callback.vader b/test/command_callback/test_html_stylelint_command_callback.vader
new file mode 100644
index 00000000..49d7d143
--- /dev/null
+++ b/test/command_callback/test_html_stylelint_command_callback.vader
@@ -0,0 +1,60 @@
+Before:
+ Save g:ale_html_stylelint_executable
+ Save g:ale_html_stylelint_use_global
+ Save g:ale_html_stylelint_options
+
+ unlet! b:executable
+
+ unlet! g:ale_html_stylelint_executable
+ unlet! g:ale_html_stylelint_use_global
+ unlet! g:ale_html_stylelint_options
+
+ call ale#test#SetDirectory('/testplugin/test/command_callback')
+ call ale#test#SetFilename('testfile.html')
+
+ runtime ale_linters/html/stylelint.vim
+
+After:
+ Restore
+
+ unlet! b:executable
+ unlet! b:ale_html_stylelint_executable
+ unlet! b:ale_html_stylelint_use_global
+ unlet! b:ale_html_stylelint_options
+
+ call ale#test#SetFilename('test.txt')
+
+ call ale#test#RestoreDirectory()
+ call ale#linter#Reset()
+
+Execute(node_modules directories should be discovered):
+ call ale#test#SetFilename('stylelint_paths/nested/testfile.html')
+
+ let b:executable = ale#path#Simplify(
+ \ g:dir
+ \ . '/stylelint_paths/node_modules/.bin/stylelint'
+ \)
+
+ AssertEqual b:executable, ale_linters#html#stylelint#GetExecutable(bufnr(''))
+ AssertEqual
+ \ ale#Escape(b:executable) . ' --stdin-filename %s',
+ \ ale_linters#html#stylelint#GetCommand(bufnr(''))
+
+Execute(The global override should work):
+ let b:ale_html_stylelint_executable = 'foobar'
+ let b:ale_html_stylelint_use_global = 1
+
+ call ale#test#SetFilename('stylelint_paths/nested/testfile.html')
+
+ AssertEqual 'foobar', ale_linters#html#stylelint#GetExecutable(bufnr(''))
+ AssertEqual
+ \ ale#Escape('foobar') . ' --stdin-filename %s',
+ \ ale_linters#html#stylelint#GetCommand(bufnr(''))
+
+Execute(Extra options should be configurable):
+ let b:ale_html_stylelint_options = '--whatever'
+
+ AssertEqual 'stylelint', ale_linters#html#stylelint#GetExecutable(bufnr(''))
+ AssertEqual
+ \ ale#Escape('stylelint') . ' --whatever --stdin-filename %s',
+ \ ale_linters#html#stylelint#GetCommand(bufnr(''))