diff --git a/django/contrib/admin/sites.py b/django/contrib/admin/sites.py index 3ff7088506..2e400c2e19 100644 --- a/django/contrib/admin/sites.py +++ b/django/contrib/admin/sites.py @@ -45,7 +45,7 @@ class AdminSite: # Text to put at the end of each page's . site_title = gettext_lazy("Django site admin") - # Text to put in each page's <h1>. + # Text to put in each page's <div id="site-name">. site_header = gettext_lazy("Django administration") # Text to put at the top of the admin index page. diff --git a/django/contrib/admin/static/admin/css/base.css b/django/contrib/admin/static/admin/css/base.css index 0bde69d013..c4b7de55f6 100644 --- a/django/contrib/admin/static/admin/css/base.css +++ b/django/contrib/admin/static/admin/css/base.css @@ -937,7 +937,7 @@ a.deletelink:focus, a.deletelink:hover { display: flex; } -#branding h1 { +#site-name { padding: 0; margin: 0; margin-inline-end: 20px; @@ -946,7 +946,7 @@ a.deletelink:focus, a.deletelink:hover { color: var(--header-branding-color); } -#branding h1 a:link, #branding h1 a:visited { +#site-name a:link, #site-name a:visited { color: var(--accent); } diff --git a/django/contrib/admin/static/admin/css/responsive.css b/django/contrib/admin/static/admin/css/responsive.css index 9ce4f67bf2..e3923448ac 100644 --- a/django/contrib/admin/static/admin/css/responsive.css +++ b/django/contrib/admin/static/admin/css/responsive.css @@ -43,7 +43,7 @@ input[type="submit"], button { justify-content: flex-start; } - #branding h1 { + #site-name { margin: 0 0 8px; line-height: 1.2; } @@ -432,7 +432,7 @@ input[type="submit"], button { padding: 15px 20px; } - .login #branding h1 { + .login #site-name { margin: 0; } diff --git a/django/contrib/admin/templates/admin/base_site.html b/django/contrib/admin/templates/admin/base_site.html index d83ac0df9b..4405998164 100644 --- a/django/contrib/admin/templates/admin/base_site.html +++ b/django/contrib/admin/templates/admin/base_site.html @@ -3,7 +3,7 @@ {% block title %}{% if subtitle %}{{ subtitle }} | {% endif %}{{ title }} | {{ site_title|default:_('Django site admin') }}{% endblock %} {% block branding %} -<h1 id="site-name"><a href="{% url 'admin:index' %}">{{ site_header|default:_('Django administration') }}</a></h1> +<div id="site-name"><a href="{% url 'admin:index' %}">{{ site_header|default:_('Django administration') }}</a></div> {% if user.is_anonymous %} {% include "admin/color_theme_toggle.html" %} {% endif %} diff --git a/docs/intro/tutorial07.txt b/docs/intro/tutorial07.txt index 71c13180fe..7810ad7fad 100644 --- a/docs/intro/tutorial07.txt +++ b/docs/intro/tutorial07.txt @@ -367,7 +367,7 @@ a section of code like: .. code-block:: html+django {% block branding %} - <h1 id="site-name"><a href="{% url 'admin:index' %}">Polls Administration</a></h1> + <div id="site-name"><a href="{% url 'admin:index' %}">Polls Administration</a><div> {% endblock %} We use this approach to teach you how to override templates. In an actual diff --git a/docs/ref/contrib/admin/index.txt b/docs/ref/contrib/admin/index.txt index d3c3884329..f8a8153a49 100644 --- a/docs/ref/contrib/admin/index.txt +++ b/docs/ref/contrib/admin/index.txt @@ -2848,9 +2848,13 @@ Templates can override or extend base admin templates as described in .. attribute:: AdminSite.site_header - The text to put at the top of each admin page, as an ``<h1>`` (a string). + The text to put at the top of each admin page, as a ``<div>`` (a string). By default, this is "Django administration". + .. versionchanged:: 5.0 + + In older versions, ``site_header`` was using an ``<h1>`` tag. + .. attribute:: AdminSite.site_title The text to put at the end of each admin page's ``<title>`` (a string). By diff --git a/docs/releases/5.0.txt b/docs/releases/5.0.txt index f6377cd59b..38b49986c5 100644 --- a/docs/releases/5.0.txt +++ b/docs/releases/5.0.txt @@ -419,6 +419,11 @@ Miscellaneous * :class:`~django.db.models.functions.Now` database function now uses ``LOCALTIMESTAMP`` instead of ``CURRENT_TIMESTAMP`` on Oracle. +* :attr:`.AdminSite.site_header` is now rendered in a ``<div>`` tag instead of + ``<h1>``. Screen reader users rely on heading elements for navigation within + a page. Having two ``<h1>`` elements was confusing and the site header wasn't + helpful as it is repeated on all pages. + .. _deprecated-features-5.0: Features deprecated in 5.0 diff --git a/tests/admin_docs/test_views.py b/tests/admin_docs/test_views.py index 4fe51f3d02..7969f6cd42 100644 --- a/tests/admin_docs/test_views.py +++ b/tests/admin_docs/test_views.py @@ -27,7 +27,7 @@ class AdminDocViewTests(TestDataMixin, AdminDocsTestCase): self.assertContains(response, "<h1>Documentation</h1>", html=True) self.assertContains( response, - '<h1 id="site-name"><a href="/admin/">Django administration</a></h1>', + '<div id="site-name"><a href="/admin/">Django administration</a></div>', ) self.client.logout() response = self.client.get(reverse("django-admindocs-docroot"), follow=True) @@ -153,7 +153,7 @@ class AdminDocViewTests(TestDataMixin, AdminDocsTestCase): ) self.assertContains( response, - '<h1 id="site-name"><a href="/admin/">Django administration</a></h1>', + '<div id="site-name"><a href="/admin/">Django administration</a></div>', ) finally: utils.docutils_is_available = True