【问题标题】:Remember CSS stylesheet change when templates are rendered in flask记住在烧瓶中呈现模板时 CSS 样式表的变化
【发布时间】:2020-12-05 10:45:35
【问题描述】:

我已经用 HTML 和 外部(静态)CSS 样式表构建了一个烧瓶应用程序。该应用程序有一个复选框,该复选框控制哪个 CSS 样式表在 JavaScript 中处于活动状态。两种不同的外部样式表的目的是允许用户在浅色(基本)和深色模式之间切换。

上述功能按预期工作。但是,当呈现新模板时,会加载包含<header>初始 CSS 样式表的 base.html 文件。

当新模板在烧瓶中呈现时,如何保持 CSS 样式表的变化?

示例

对于每个呈现的 html 页面,base.html 都会被扩展。此文件包含 base-theme.css 文件作为初始 CSS 样式表。

base.html

<!doctype html>
<html lang="en">

<head>
    <meta charset="utf-8">
    <title>Application Name</title>
    <meta name="description" content="Application Name">
    <link rel="favorite icon" href="{{ url_for('static', filename='favicon.ico') }}">
    <link rel="stylesheet" href="{{ url_for('static', filename='css/base-theme.css') }}" id="stylesheet_toggle">
    <script type="text/javascript" src="{{ url_for('static', filename='js/switch_mode.js') }}"></script>
</head>

<body>
    {% block body %}{% endblock %}
</body>

</html>

选中复选框 (topnav_right_mode_toggle) 时,CSS 样式表会使用 JavaScript 从 base-theme.css 更改为 dark-theme.css

switch_mode.js

window.onload = function () {
    const toggle = document.getElementById("topnav_right_mode_toggle");
    const theme = document.getElementById("stylesheet_toggle");

    toggle.addEventListener("click", function () {
        if (theme.getAttribute("href") == "/static/css/base-theme.css") {
            theme.href = "/static/css/dark-theme.css";
        } else {
            theme.href = "/static/css/base-theme.css";
        }
    });
}

到目前为止,一切都很好......

现在触发了另一个端点,并为此端点呈现了另一个 html 文件。此 html 文件扩展了 base.html,并且因为 base.html 包含 CSS 样式表:base-theme.css,所以对样式表:dark-theme.css 的更改已撤消。

当另一个 html 文件被渲染时,我如何记住样式表的变化?

【问题讨论】:

  • 如果问题不清楚请告诉我...

标签: python css flask jinja2


【解决方案1】:

您真正需要做的就是存储此信息,以便它在对服务器的请求之间以及因此在您应用的不同页面之间持续存在。

一个巧妙的解决方案是使用浏览器的localStorage

您可以将所选主题的位置存储在 localStorage 中并在每次页面加载时检索,例如

window.onload = function () {
    const toggle = document.getElementById("topnav_right_mode_toggle");
    const theme = document.getElementById("stylesheet_toggle");
    const selected = localStorage.getItem("css");
    if (selected !== null) {
      theme.href = selected;
    }

    toggle.addEventListener("click", function () {
        if (theme.getAttribute("href") == "/static/css/base-theme.css") {
            theme.href = "/static/css/dark-theme.css";
        } else {
            theme.href = "/static/css/base-theme.css";
        }
        localStorage.setItem("css", theme.href);
    });
}

【讨论】:

  • 这成功了,非常感谢!在过去的几天里,我找不到任何(可接受的)解决方案。
  • 您说:“一个巧妙的解决方案是..”,请问您是否认为有一种解决方案可以在不使用 JS 的情况下实现这一目标?如果可能的话,我想在不使用 JS 的情况下完成这个应用程序。注意 JS,但对于这个用例来说更好。您认为不使用 JS(即仅 HTML 和 CSS)就可以实现浅色/深色主题(在烧瓶中)吗?
  • 由于您的初始代码使用了 JavaScript,因此我提供了可能是最简单、最干净的 JS 解决方案。一般来说,这些信息最好由前端而不是后端来管理。
  • 纯 Python(后端)解决方案可能的 - 但相比之下它会相当混乱。您将与服务器打乒乓球,因为每次更改时都必须与服务器通信主题信息。这几乎意味着每次更改主题时都会重新加载页面(这对用户来说很糟糕)。在页面请求之间传递信息也很麻烦(尤其是对于 GET 请求)——除非你 store 主题选择服务器端,例如在数据库中。
  • 存在使用 cookie 的替代解决方案,或者您可以在后台向烧瓶服务器发出 POST 请求以更新所选主题(从而防止页面重新加载)——但这两种替代方案都需要 JS。
【解决方案2】:

我在我的烧瓶网站中执行此操作的方式是将用户选择的主题存储在数据库中,特别是作为“设置”表中的布尔值,该表与“用户”表具有一对一的关系。

这让我可以利用 Jinja 并在 base.html 模板中简单地做这样的事情:

<html>
<head>
(...)

{% if current_user.settings.dark_theme %}
  <body class="dark_theme">
{% else %}
  <body>
{% endif %}

(...)
</body>
</html>

然后您可以开始使用如下变量设置您的 css 样式表:

:root {
  --primary-color: #ffffff;
}

.dark_theme {
  --primary-color: #000000;
}
body {
  background-color: var(--primary-color);
}

【讨论】:

    猜你喜欢
    • 2016-05-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-09-24
    • 1970-01-01
    相关资源
    最近更新 更多