diff --git a/doc/usage/configuration.rst b/doc/usage/configuration.rst
index ff428a6554f..941b6038d9d 100644
--- a/doc/usage/configuration.rst
+++ b/doc/usage/configuration.rst
@@ -1065,6 +1065,20 @@ that use Sphinx's HTMLWriter class.
.. versionadded:: 1.8
+.. confval:: html_codeblock_linenos_style
+
+ The style of line numbers for code-blocks.
+
+ * ``'table'`` -- display line numbers using ``
`` tag
+ * ``'inline'`` -- display line numbers using ```` tag (default)
+
+ .. versionadded:: 3.2
+ .. versionchanged:: 4.0
+
+ It defaults to ``'inline'``.
+
+ .. deprecated:: 4.0
+
.. confval:: html_context
A dictionary of values to pass into the template engine's context for all
diff --git a/sphinx/builders/html/__init__.py b/sphinx/builders/html/__init__.py
index 71952199bbb..d5264e43e97 100644
--- a/sphinx/builders/html/__init__.py
+++ b/sphinx/builders/html/__init__.py
@@ -23,7 +23,7 @@
from sphinx import version_info as sphinx_version
from sphinx.application import Sphinx
from sphinx.builders import Builder
-from sphinx.config import Config
+from sphinx.config import ENUM, Config
from sphinx.deprecation import RemovedInSphinx70Warning, deprecated_alias
from sphinx.domains import Domain, Index, IndexEntry
from sphinx.environment import BuildEnvironment
@@ -1371,6 +1371,8 @@ def setup(app: Sphinx) -> Dict[str, Any]:
app.add_config_value('html_search_scorer', '', None)
app.add_config_value('html_scaled_image_link', True, 'html')
app.add_config_value('html_baseurl', '', 'html')
+ app.add_config_value('html_codeblock_linenos_style', 'inline', 'html', # RemovedInSphinx70Warning # NOQA
+ ENUM('table', 'inline'))
app.add_config_value('html_math_renderer', None, 'env')
app.add_config_value('html4_writer', False, 'html')
diff --git a/sphinx/writers/html.py b/sphinx/writers/html.py
index cb0794c04d4..680a47ac8f1 100644
--- a/sphinx/writers/html.py
+++ b/sphinx/writers/html.py
@@ -446,11 +446,14 @@ def visit_literal_block(self, node: Element) -> None:
return super().visit_literal_block(node)
lang = node.get('language', 'default')
- linenos = node.get('linenos', False) and "inline"
+ linenos = node.get('linenos', False)
highlight_args = node.get('highlight_args', {})
highlight_args['force'] = node.get('force', False)
opts = self.config.highlight_options.get(lang, {})
+ if linenos and self.config.html_codeblock_linenos_style:
+ linenos = self.config.html_codeblock_linenos_style
+
highlighted = self.highlighter.highlight_block(
node.rawsource, lang, opts=opts, linenos=linenos,
location=node, **highlight_args
diff --git a/sphinx/writers/html5.py b/sphinx/writers/html5.py
index a169c606996..a68951a7f49 100644
--- a/sphinx/writers/html5.py
+++ b/sphinx/writers/html5.py
@@ -404,11 +404,14 @@ def visit_literal_block(self, node: Element) -> None:
return super().visit_literal_block(node)
lang = node.get('language', 'default')
- linenos = node.get('linenos', False) and "inline"
+ linenos = node.get('linenos', False)
highlight_args = node.get('highlight_args', {})
highlight_args['force'] = node.get('force', False)
opts = self.config.highlight_options.get(lang, {})
+ if linenos and self.config.html_codeblock_linenos_style:
+ linenos = self.config.html_codeblock_linenos_style
+
highlighted = self.highlighter.highlight_block(
node.rawsource, lang, opts=opts, linenos=linenos,
location=node, **highlight_args
diff --git a/tests/test_build_html.py b/tests/test_build_html.py
index 1a717f15210..fa0bbac7c3d 100644
--- a/tests/test_build_html.py
+++ b/tests/test_build_html.py
@@ -1598,8 +1598,21 @@ def test_html_scaled_image_link(app):
context)
-@pytest.mark.sphinx('html', testroot='reST-code-block')
-def test_html_codeblock_linenos_style(app):
+@pytest.mark.sphinx('html', testroot='reST-code-block',
+ confoverrides={'html_codeblock_linenos_style': 'table'})
+def test_html_codeblock_linenos_style_table(app):
+ app.build()
+ content = (app.outdir / 'index.html').read_text(encoding='utf8')
+
+ assert ('1\n'
+ '2\n'
+ '3\n'
+ '4
') in content
+
+
+@pytest.mark.sphinx('html', testroot='reST-code-block',
+ confoverrides={'html_codeblock_linenos_style': 'inline'})
+def test_html_codeblock_linenos_style_inline(app):
app.build()
content = (app.outdir / 'index.html').read_text(encoding='utf8')