From cd413bd78ac65bd4282d26cc279bfd1bd4de707d Mon Sep 17 00:00:00 2001 From: Howard Cox Date: Fri, 2 Jun 2023 11:54:07 +0100 Subject: [PATCH] Fixed #34621 -- Made admin site header render in
tag. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This was problematic for screen reader users because they use headings to navigate. Having two

is confusing, and the one in the header wasn’t particularly helpful since it’s the same on all pages. --- django/contrib/admin/sites.py | 2 +- django/contrib/admin/static/admin/css/base.css | 4 ++-- django/contrib/admin/static/admin/css/responsive.css | 4 ++-- django/contrib/admin/templates/admin/base_site.html | 2 +- docs/intro/tutorial07.txt | 2 +- docs/ref/contrib/admin/index.txt | 6 +++++- docs/releases/5.0.txt | 5 +++++ tests/admin_docs/test_views.py | 4 ++-- 8 files changed, 19 insertions(+), 10 deletions(-) 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