• 日常搜索
  • 百度一下
  • Google
  • 在线工具
  • 搜转载

使用CSS和JavaScript创建一个响应式管理仪表板布局

在这个更新的教程中,我们将使用 css 和一些 javascript 创建一个响应式管理仪表板布局。为了构建它,我们将从 wordpress 仪表板中借鉴一些想法,例如其可折叠的侧边栏菜单。

在整个教程中,我们将面临许多挑战,但这些挑战将为我们提供提高前端技能的良好实践。

管理仪表板演示

事不宜迟,让我们看看最终的管理仪表板演示。注意以下几点:

  • 点击侧边栏底部的折叠按钮以查看可折叠导航的运行情况。

  • 点击侧边栏底部的切换开关以显示明暗管理主题。

  • 查看全屏版本以发挥其响应能力。

See the Pen  Building a Dashboard Layout With CSS and a Touch of JavaScript by Envato Tuts+ (@tutsplus)  on CodePen.

或者,如果您想用 JavaScript 和 CSS 编写自己的仪表板,请继续阅读本教程。

1. 从页面标记开始

要开始标记,我们需要一个 svg、一个标题和一个部分:

<svg style="display:none;">...</svg>

<header class="page-header">...</header>

<section class="page-content">...</section>

SVG 精灵

正如您可能想象的那样,对于任何管理仪表板,我们都需要一堆图标。值得庆幸的是,Envato Elements提供了不断扩展的有用矢量图标集合,因此让我们利用该库并下载这些 贸易和仪表板图标。

使用CSS和JavaScript创建一个响应式管理仪表板布局  第1张

贸易和仪表板图标

与其通过imgorsvg标记将它们直接包含在页面上,不如更进一步,创建一个 SVG 精灵。为此,我们将所有图标包装在一个 SVG 容器中。容器应该是隐藏的,所以我们将应用display: none 到它。如果我们不隐藏它,页面顶部会出现一个很大的空白区域。

每个图标都将放置在symbol具有唯一 ID 和 viewBox属性的元素内,该属性取决于图标大小。然后,我们可以在需要时通过调用use元素来渲染目标图标(我会在一分钟内向您展示如何)。 

此外,我们将把我们的标志放在这个容器中。 

稍后,我们将研究这些 SVG 的颜色将如何根据主题模式而变化,但现在让我们熟悉 SVG 精灵所需的标记:

<svg style="display:none;">

  <symbol id="logo" viewBox="0 0 140 59">

    <g>

      <path d="M6.8 57c0 .4-.1.7-.2.9-.1.2-.3.4-.4.5-.1.1-.4.199-.5.3-.2 0-.3.1-.5.1-.1 0-.3 0-.5-.1-.2 0-.4-.101-.5-.3-.2 0-.4-.2-.5-.4-.1-.2-.2-.5-.2-.9V44.7h-2c-.3 0-.6-.101-.8-.2-.2-.1-.3-.2-.5-.4s-.2-.3-.2-.4v-.4c0-.1 0-.2.1-.399 0-.2.1-.301.2-.4.1-.1.3-.3.5-.4.1 0 .4-.1.7-.1h2.1v-3.5c0-1 .1-1.9.3-2.7C4.1 35 4.5 34.3 5 33.7c.5-.6 1.1-1.1 1.9-1.4.8-.3 1.7-.5 2.7-.5.9 0 1.5.101 1.8.4.3.3.5.6.5 1.1 0 .3-.1.601-.3.9-.2.3-.6.4-1.2.4h-.6c-.6 0-1.1.101-1.5.301-.4.199-.7.5-.9.8C7.2 36 7 36.5 7 37c-.1.5-.1 1-.1 1.6V42h2.7c.3 0 .6.1.8.2.2.1.3.2.5.399.1.101.2.301.2.401 0 .2.1.3.1.4 0 .1 0 .3-.1.399 0 .2-.1.3-.2.4-.1.1-.3.3-.5.399-.2.101-.5.2-.8.2H6.8V57z" />

      <path d="M30.4 50.2c0 1.3-.2 2.5-.7 3.5-.5 1.1-1.1 2-1.9 2.8-.8.8-1.8 1.4-2.8 1.8-1.1.4-2.3.601-3.5.601-1.3 0-2.4-.2-3.5-.601-1.1-.399-2-1-2.8-1.8-.8-.8-1.4-1.7-1.9-2.8-.5-1.101-.7-2.2-.7-3.5s.2-2.4.7-3.5c.5-1.101 1.1-2 1.9-2.7.8-.8 1.7-1.4 2.8-1.8 1.1-.4 2.3-.601 3.5-.601 1.3 0 2.4.2 3.5.601 1.1.399 2 1 2.8 1.8.8.8 1.4 1.7 1.9 2.7.5 1.1.7 2.3.7 3.5zm-3.4 0c0-.8-.1-1.5-.4-2.3-.2-.7-.6-1.4-1.1-1.9s-1-1-1.7-1.3c-.7-.3-1.5-.5-2.4-.5s-1.7.2-2.4.5-1.3.8-1.7 1.3c-.5.5-.8 1.2-1.1 1.9-.2.699-.4 1.5-.4 2.3s.1 1.5.4 2.3c.2.7.6 1.4 1.1 1.9.5.6 1 1 1.7 1.3s1.5.5 2.4.5 1.7-.2 2.4-.5 1.3-.8 1.7-1.3c.5-.601.8-1.2 1.1-1.9.3-.7.4-1.5.4-2.3z" />

      <path d="M38.1 44.8h.1c.4-.899 1-1.7 1.9-2.3s1.8-.9 2.9-.9c.5 0 1 .101 1.3.301.4.199.6.6.6 1.1 0 .6-.2 1-.6 1.2-.4.2-.8.3-1.4.3h-.2c-1.3 0-2.4.5-3.2 1.4-.8.899-1.3 2.3-1.3 4.1v7c0 .4-.1.7-.2.9-.1.199-.3.399-.4.5-.2.1-.4.199-.5.3-.2 0-.3.1-.5.1-.1 0-.3 0-.5-.1-.2 0-.4-.101-.5-.3-.1-.2-.3-.301-.4-.5C35 57.7 35 57.4 35 57V43.5c0-.4.1-.7.2-.9.1-.199.3-.399.4-.5.2-.1.3-.199.5-.199s.3-.101.5-.101c.1 0 .3 0 .4.101.2 0 .3.1.5.199.2.101.3.301.4.5.1.2.2.5.2.9v1.3z" />

      <path d="M49.2 51.3c0 .7.2 1.4.5 2 .3.601.7 1.2 1.2 1.601.5.5 1.1.8 1.7 1.1s1.3.4 2 .4c1 0 1.8-.2 2.5-.5.7-.4 1.2-.801 1.8-1.2.2-.2.4-.3.6-.4.2-.301.3-.301.5-.301.4 0 .7.1 1 .4.3.199.4.6.4 1 0 .1 0 .3-.1.5s-.2.4-.4.7c-1.6 1.7-3.7 2.5-6.3 2.5-1.3 0-2.4-.199-3.5-.6s-2-1-2.8-1.8c-.8-.8-1.4-1.7-1.8-2.7-.4-1.1-.7-2.3-.7-3.6 0-1.301.2-2.5.6-3.5.4-1.101 1-2 1.8-2.801.8-.8 1.7-1.399 2.7-1.8 1-.399 2.2-.6 3.4-.6 2.1 0 3.8.6 5.2 1.8s2.3 2.9 2.6 5.2c0 .3.1.5.1.6v.5c0 1.101-.6 1.7-1.7 1.7H49.2V51.3zm9.9-2.5c0-.7-.1-1.3-.3-1.8-.2-.6-.5-1.1-.9-1.5s-.9-.7-1.4-1c-.6-.2-1.2-.4-2-.4-.7 0-1.4.101-2 .4-.6.2-1.2.6-1.6 1-.5.4-.8.9-1.1 1.5-.3.6-.5 1.2-.5 1.8h9.8z" />

      <path d="M77.9 55.1c.399-.3.8-.5 1.199-.5.4 0 .7.101 1 .4.2.3.4.6.4.9 0 .199 0 .5-.1.699a1.856 1.856 0 01-.599.701c-.7.5-1.399.9-2.3 1.2s-1.8.4-2.7.4c-1.3 0-2.5-.2-3.5-.601-1.1-.399-2-1-2.8-1.8s-1.4-1.7-1.8-2.7c-.4-1.1-.7-2.3-.7-3.6s.2-2.5.7-3.601c.4-1.1 1.1-2 1.8-2.8.8-.8 1.7-1.399 2.8-1.8 1.101-.4 2.2-.6 3.5-.6.9 0 1.7.1 2.601.399C78.2 42 79 42.4 79.6 43l.7.7c.101.2.2.5.2.7 0 .399-.1.8-.4 1-.3.3-.6.399-1 .399-.199 0-.399 0-.5-.1-.2-.099-.4-.199-.7-.499-.301-.3-.7-.5-1.2-.7s-1-.3-1.7-.3c-.9 0-1.6.2-2.3.5s-1.2.8-1.7 1.3-.8 1.2-1.1 1.9c-.2.699-.4 1.5-.4 2.3s.1 1.5.3 2.2c.2.699.6 1.3 1 1.899.5.5 1 1 1.7 1.3.7.301 1.4.5 2.3.5.7 0 1.3-.1 1.8-.3.4-.099.9-.299 1.3-.699z" />

      <path d="M94.6 56.2h-.1c-.6.899-1.4 1.6-2.3 2.1-.9.5-2 .7-3.3.7-.7 0-1.301-.1-2-.3-.7-.2-1.4-.5-1.9-.9-.6-.399-1.1-.899-1.4-1.6-.4-.7-.6-1.5-.6-2.4 0-1.3.3-2.2 1-3 .7-.7 1.6-1.3 2.7-1.7 1.1-.399 2.3-.6 3.7-.699 1.399-.101 2.8-.2 4.199-.2v-.5c0-1.2-.399-2.101-1.1-2.7s-1.7-.9-3-.9c-.7 0-1.4.101-2 .301-.6.199-1.3.5-1.9 1-.3.199-.699.3-1 .3-.3 0-.6-.101-.899-.4-.2-.2-.4-.6-.4-.899 0-.2.101-.5.2-.7s.3-.4.6-.601c.7-.5 1.601-1 2.5-1.3 1-.3 2-.5 3.2-.5s2.2.2 3.101.5c.899.3 1.6.8 2.199 1.4.601.6 1 1.3 1.301 2.1.3.8.399 1.601.399 2.5V56.9c0 .3-.1.6-.2.899-.1.201-.2.401-.4.501-.2.101-.3.2-.5.2s-.3.1-.4.1c-.1 0-.3 0-.399-.1-.2 0-.301-.1-.5-.2-.201-.1-.301-.3-.401-.5s-.2-.5-.2-.899v-.7h-.2zm-.9-5.5c-.8 0-1.7 0-2.5.1-.9.101-1.7.2-2.4.4s-1.3.5-1.8.9-.7 1-.7 1.7c0 .5.101.9.3 1.2.2.3.5.6.801.8.3.2.699.4 1.1.4.4.1.8.1 1.2.1 1.5 0 2.7-.5 3.5-1.399.8-.9 1.2-2.101 1.2-3.5v-.9h-.7v.199z" />

      <path d="M111.4 45.4c-.5-.5-1-.801-1.5-1-.5-.2-1.101-.301-1.601-.301-.399 0-.7 0-1.1.101-.4.1-.7.2-1 .399-.3.2-.5.4-.7.7s-.3.601-.3 1c0 .7.3 1.2.899 1.601.601.3 1.601.6 2.801.899.8.2 1.5.4 2.199.7.7.3 1.301.6 1.801 1s.899.8 1.199 1.4c.301.5.4 1.199.4 1.899 0 1-.2 1.8-.6 2.5-.4.7-.9 1.2-1.5 1.7-.601.4-1.301.7-2.101.9-.8.199-1.6.3-2.399.3-1 0-2-.2-2.9-.5-1-.3-1.8-.8-2.5-1.4-.3-.3-.5-.5-.6-.7-.098-.198-.098-.398-.098-.598 0-.4.101-.8.4-1 .3-.3.6-.4 1-.4.399 0 .8.2 1.2.5.5.5 1.1.801 1.699 1.101.601.3 1.2.399 1.9.399.4 0 .8 0 1.2-.1.399-.1.7-.2 1-.4.3-.199.6-.399.8-.699.2-.301.3-.7.3-1.2 0-.8-.399-1.3-1.1-1.7s-1.8-.7-3.2-1c-.6-.1-1.1-.3-1.7-.5-.6-.2-1.1-.5-1.6-.8s-.8-.8-1.101-1.3c-.3-.5-.399-1.2-.399-2 0-.9.2-1.601.5-2.301.401-.6.801-1.2 1.401-1.6.601-.4 1.2-.7 2-.9.7-.199 1.5-.3 2.301-.3.899 0 1.699.101 2.6.4.8.3 1.6.7 2.2 1.2.3.3.5.5.6.699.101.2.101.4.101.601 0 .399-.101.7-.4 1s-.6.399-1 .399c-.402-.199-.802-.399-1.102-.699z" />

      <path d="M126 58.4c-.6.3-1.3.399-2.1.399-1.601 0-2.801-.399-3.601-1.3s-1.2-2.2-1.2-3.9v-9H117.2c-.3 0-.601 0-.8-.1-.2-.1-.4-.2-.5-.3-.101-.101-.2-.3-.2-.4 0-.2-.101-.3-.101-.399 0-.101 0-.2.101-.4 0-.2.1-.3.2-.4.1-.1.3-.3.5-.399.199-.101.5-.2.8-.2h1.899v-3.2c0-.399.101-.7.2-.899.101-.2.3-.4.4-.601.2-.1.399-.2.5-.3.2 0 .3-.1.5-.1.1 0 .3 0 .5.1.2 0 .3.1.5.3.2.101.3.3.399.601.101.199.2.6.2.899V42h3.2c.3 0 .6.1.8.2.2.1.3.2.5.399.102.101.202.301.202.401 0 .2.1.3.1.4 0 .1 0 .3-.1.399 0 .2-.1.3-.2.4-.1.1-.3.3-.5.3-.2.1-.5.1-.8.1h-3.2V53.2c0 1 .2 1.7.5 2.1.4.4.8.601 1.4.601.2 0 .5 0 .7-.101.199-.1.399-.1.6-.1.4 0 .7.1.9.399.199.301.3.601.3.9s-.101.5-.2.7c0 .401-.2.601-.5.701z" />

      <path d="M133.2 44.8h.1c.4-.899 1-1.7 1.9-2.3.899-.6 1.8-.9 2.899-.9.5 0 1 .101 1.301.301.4.199.6.599.6 1.099 0 .6-.2 1-.6 1.2-.4.2-.801.3-1.4.3h-.2c-1.3 0-2.399.5-3.2 1.4-.8.899-1.3 2.3-1.3 4.1v7c0 .4-.1.7-.2.9-.1.199-.3.399-.399.5-.101.1-.4.199-.5.3-.2 0-.3.1-.5.1-.101 0-.3 0-.5-.1-.2 0-.4-.101-.5-.3-.2-.101-.3-.301-.4-.5-.1-.2-.2-.5-.2-.9V43.5c0-.4.101-.7.2-.9.101-.199.3-.399.4-.5.2-.1.3-.199.5-.199s.3-.101.5-.101c.1 0 .3 0 .399.101.2 0 .301.1.5.199.2.101.301.301.4.5.1.2.2.5.2.9v1.3z" />

    </g>

    <g>

      <g>

        <path fill="#08A6DF" d="M70 32.9c-9.1 0-16.5-7.4-16.5-16.5 0-4.8 2.1-9.3 5.7-12.4.5-.4 1.2-.4 1.6.1.4.5.4 1.2-.1 1.6-3.1 2.7-4.9 6.6-4.9 10.7 0 7.8 6.4 14.2 14.2 14.2s14.2-6.4 14.2-14.2c0-7.8-6.4-14.1-14.2-14.1-1.9 0-3.7.4-5.4 1.1-.6.2-1.3 0-1.5-.6-.2-.6 0-1.3.6-1.5C65.7.4 67.8 0 70 0c9.1 0 16.5 7.4 16.5 16.5S79.1 32.9 70 32.9z" />

      </g>

      <g>

        <path fill="#7C2A8A" d="M70 28.4c-6.6 0-11.9-5.4-11.9-11.9 0-6.6 5.4-11.9 11.9-11.9 5 0 9.5 3.2 11.2 7.9.5 1.3.7 2.6.7 4 0 .6-.5 1.1-1.101 1.1-.6 0-1.1-.5-1.1-1.1 0-1.1-.2-2.2-.601-3.3-1.399-3.8-5-6.4-9.1-6.4-5.3 0-9.6 4.3-9.6 9.6s4.3 9.6 9.6 9.6c.6 0 1.1.5 1.1 1.1.002.8-.498 1.3-1.098 1.3z" />

      </g>

      <g>

        <path fill="#EC1848" d="M70 23.9c-4.1 0-7.4-3.3-7.4-7.4s3.3-7.4 7.4-7.4c.6 0 1.1.5 1.1 1.1 0 .6-.5 1.1-1.1 1.1-2.8 0-5.1 2.3-5.1 5.1s2.3 5.1 5.1 5.1 5.1-2.3 5.1-5.1c0-.6.5-1.1 1.101-1.1.6 0 1.1.5 1.1 1.1.099 4.2-3.201 7.5-7.301 7.5z" />

      </g>

    </g>

  </symbol>

  <symbol id="down" viewBox="0 0 16 16">

    <polygon points="3.81 4.38 8 8.57 12.19 4.38 13.71 5.91 8 11.62 2.29 5.91 3.81 4.38" />

  </symbol>

  <symbol id="users" viewBox="0 0 16 16">

    <path d="M8,0a8,8,0,1,0,8,8A8,8,0,0,0,8,0ZM8,15a7,7,0,0,1-5.19-2.32,2.71,2.71,0,0,1,1.7-1,13.11,13.11,0,0,0,1.29-.28,2.32,2.32,0,0,0,.94-.34,1.17,1.17,0,0,0-.27-.7h0A3.61,3.61,0,0,1,5.15,7.49,3.18,3.18,0,0,1,8,4.07a3.18,3.18,0,0,1,2.86,3.42,3.6,3.6,0,0,1-1.32,2.88h0a1.13,1.13,0,0,0-.27.69,2.68,2.68,0,0,0,.93.31,10.81,10.81,0,0,0,1.28.23,2.63,2.63,0,0,1,1.78,1A7,7,0,0,1,8,15Z" />

  </symbol>

   

  <!-- more symbols here -->

</svg>

实际上,这就是我们创建内联 SVG 精灵所需的全部内容。

标题

继续我们的管理仪表板布局,让我们看看页眉。 

在其中,我们将定义一个nav元素,作为以下元素的包装器:

  • 标志。

  • 将在移动屏幕上切换菜单的折叠按钮。

  • 菜单本身。这将包含菜单链接、两个标题、一个明暗模式开关和折叠/展开按钮。拥有两个单独的菜单并将标题放在它们之外可能在语义上更正确,但如果您愿意,您可以以不同的方式处理事情。

以下是它在宽屏 (>767px) 上的外观:


使用CSS和JavaScript创建一个响应式管理仪表板布局  第2张


头文件结构:

<header class="page-header">

  <nav>

    <a href="#0" aria-label="forecastr logo" class="logo">

      <svg width="140" height="49">

        <use xlink:href="#logo"></use>

      </svg>

    </a>

    <button class="toggle-mob-menu" aria-expanded="false" aria-label="open menu">

      <svg width="20" height="20" aria-hidden="true">

        <use xlink:href="#down"></use>

      </svg>

    </button>

    <ul class="admin-menu">

      <li class="menu-heading">

        <h3>Admin</h3>

      </li>

      <li>

        <a href="#0">

          <svg>

            <use xlink:href="#pages"></use>

          </svg>

          <span>Pages</span>

        </a>

      </li>

       

      <!-- more list items here -->

       

      <li>

        <div class="switch">

          <input type="checkbox" id="mode" checked>

          <label for="mode">

            <span></span>

            <span>Dark</span>

          </label>

        </div>

        <button class="collapse-btn" aria-expanded="true" aria-label="collapse menu">

          <svg aria-hidden="true">

            <use xlink:href="#collapse"></use>

          </svg>

          <span>Collapse</span>

        </button>

      </li>

    </ul>

  </nav>

</header>

注意上面代码中的两件事:

  • 我们如何使用 use元素来引用目标元素。

  • 我们添加到切换按钮的 ARIA 属性 ( aria-expanded, aria-label, )。aria-hidden这些属性将帮助我们使组件更易于访问。稍后,我们将讨论如何根据按钮的状态更新它们的值。

部分

该部分将包含两个嵌套部分。

<section class="page-content">  <!-- two sections here --></section>

第 1 节

在第一部分中,我们将放置搜索表单和有关当前登录用户的一些信息(姓名、头像和通知)。

这是它在宽屏 (>767px) 上的外观:

使用CSS和JavaScript创建一个响应式管理仪表板布局  第3张

部分结构:

<section class="search-and-user">

  <form>

    <input type="search" placeholder="Search Pages...">

    <button type="submit" aria-label="submit form">

      <svg aria-hidden="true">

        <use xlink:href="#search"></use>

      </svg>

    </button>

  </form>

  <div class="admin-profile">

    <span class="greeting">...</span>

    <div class="notifications">

      <span class="badge">...</span>

      <svg>

        <use xlink:href="#users"></use>

      </svg>

    </div>

  </div>

</section>

同样,请注意我们向提交按钮添加了一些 ARIA 属性。

第 2 节

在第二部分中,为了用一些虚拟内容丰富演示,我们将放置一堆文章占位符。这些通常可能包含表格数据、图表或某种类型的提要。

“最多使用 5-7 个不同的小部件来创建视图。否则,用户将很难集中注意力并获得清晰的概览。” ——塔拉斯·巴库塞维奇

这是它在宽屏 (>767px) 上的外观:


使用CSS和JavaScript创建一个响应式管理仪表板布局  第4张
根据 UX 最佳实践,您可能不需要这么多部分


部分结构:

<section class="grid">

  <article></article>

  <article></article>

  <article></article>

  <article></article>

  <article></article>

  <article></article>

  <article></article>

  <article></article>

</section>

2. 定义一些基本样式

准备好管理仪表板的标记后,我们将继续使用 CSS。与往常一样,第一步是指定一些 CSS 变量和常见的重置样式:

:root {

  --page-header-bgColor: #242e42;

  --page-header-bgColor-hover: #1d2636;

  --page-header-txtColor: #dde9f8;

  --page-header-headingColor: #7889a4;

  --page-header-width: 220px;

  --page-content-bgColor: #f0f1f6;

  --page-content-txtColor: #171616;

  --page-content-blockColor: #fff;

  --white: #fff;

  --black: #333;

  --blue: #00b9eb;

  --red: #ec1848;

  --border-radius: 4px;

  --box-shadow: 0 0 10px -2px rgba(0, 0, 0, 0.075);

  --switch-bgLightModeColor: #87cefa;

  --switch-sunColor: gold;

  --switch-moonColor: #f4f4f4;

  --switch-bgDarkModeColor: #1f1f27;

}

 

* {

  padding: 0;

  margin: 0;

  box-sizing: border-box;

}

 

ul {

  list-style: none;

}

 

a,

button {

  color: inherit;

}

 

a {

  text-decoration: none;

}

 

button {

  background: none;

  cursor: pointer;

}

 

input {

  -webkit-appearance: none;

}

 

[type="checkbox"] {

  position: absolute;

  left: -9999px;

}

 

label {

  cursor: pointer;

}

 

button,

input {

  border: none;

}

 

svg {

  display: block;

}

 

body {

  font: 16px/1.5 "Lato", sans-serif;

}

注意:为简单起见,我不会在教程中介绍所有CSS 规则。这里有将近 550 行 CSS。如果您愿意,您可以通过单击演示项目的CSS选项卡来检查它们。除此之外,如果你正在构建一个生产站点,使用像Sass这样的 CSS 预处理器 来组织这些样式可能更易于管理。

3. 定义主仪表板样式

此时,我们已准备好专注于页面样式。

样式标题

标题将是一个固定位置的元素。它的宽度将为 220 像素,其高度等于视口高度。如果其内容超过视口高度,将出现一个垂直滚动条。

该nav元素将表现为最小高度为 100% 的 flex 容器。请记住,它的直接孩子是三个: 

  1. 标志

  2. 移动菜单切换按钮

  3. 菜单

切换按钮仅在小屏幕 (<768px) 上可见。以下是我们需要的样式:

/*CUSTOM VARIABLES HERE*/

 

.page-header {

  position: fixed;

  top: 0;

  left: 0;

  right: 0;

  bottom: 0;

  overflow: auto;

  padding-top: 20px;

  width: var(--page-header-width);

  color: var(--page-header-txtColor);

  background: var(--page-header-bgColor);

}

 

.page-header nav {

  display: flex;

  flex-direction: column;

  min-height: 100%;

}

 

.page-header .toggle-mob-menu {

  display: none;

}

提示:如果您更喜欢覆盖整个页面高度的绝对定位标题,请添加以下样式:

body {

  position: relative;

}

 

.page-header {

  position: absolute;

  top: 0;

  left: 0;

  height: 100%;

   

  /*remove these styles*/

  /*position: fixed;

  top: 0;

  left: 0;

  right: 0;

  bottom: 0;

  overflow: auto;*/

}

菜单样式

菜单将作为一个弹性容器,我们会给它flex: 1,所以它会扩展并覆盖整个父级高度。

最后一个菜单项将被赋予a  margin-top: auto,因为它应该位于菜单的最底部。当标题滚动条不出现时,这种行为会更加清晰。要对其进行测试,请尝试删除一些菜单项或在高屏幕上查看演示。

菜单内的链接和按钮也将充当弹性容器,它们的内容(文本和图标)应该垂直对齐。

与其他菜单元素相比,菜单标题会小一些。此外,我们将增加字符之间的间距。

这是菜单样式的一部分:


/*CUSTOM VARIABLES HERE*/

 

.page-header .admin-menu {

  display: flex;

  flex-direction: column;

  flex-grow: 1;

  margin-top: 35px;

}

 

.page-header .admin-menu li:last-child {

  margin-top: auto;

  margin-bottom: 20px;

}

 

.page-header .admin-menu li > * {

  width: 100%;

  padding: 12px 15px;

}

 

.page-header .admin-menu .menu-heading h3 {

  text-transform: uppercase;

  letter-spacing: 0.15em;

  font-size: 12px;

  margin-top: 12px;

  color: var(--page-header-headingColor);

}

 

.page-header .admin-menu a,

.page-header .admin-menu button {

  display: flex;

  align-items: center;

  font-size: 0.9rem;

}


切换深色和浅色主题

为了构建开关,我们将从另一个解释如何创建拨动开关的教程中借鉴很多样式。请务必查看并了解我们如何使用 CSS 复选框 hack 技术来实现它。

我们的仪表板将支持两种主题选项:浅色选项和深色选项。默认情况下,黑暗将处于活动状态,如下所示:


使用CSS和JavaScript创建一个响应式管理仪表板布局  第5张


当我们点击开关时,它的外观会改变如下:


使用CSS和JavaScript创建一个响应式管理仪表板布局  第6张


以下是相关的样式:

/*CUSTOM VARIABLES HERE*/

 

.switch label {

  display: grid;

  grid-template-columns: auto auto;

  grid-column-gap: 10px;

  align-items: center;

  justify-content: flex-start;

}

 

.switch span:first-child {

  position: relative;

  width: 50px;

  height: 26px;

  border-radius: 15px;

  box-shadow: inset 0 0 5px rgba(0, 0, 0, 0.4);

  background: var(--switch-bgLightModeColor);

  transition: all 0.3s;

}

 

.switch span:first-child::before,

.switch span:first-child::after {

  content: "";

  position: absolute;

  border-radius: 50%;

}

 

.switch span:first-child::before {

  top: 1px;

  left: 1px;

  width: 24px;

  height: 24px;

  background: var(--white);

  z-index: 1;

  transition: transform 0.3s;

}

 

.switch span:first-child::after {

  top: 50%;

  right: 8px;

  width: 10px;

  height: 10px;

  transform: translateY(-50%);

  background: var(--switch-sunColor);

  box-shadow: 0 0 4px 2px #ffdb1a;

}

 

.switch [type="checkbox"]:checked + label span:first-child {

  background: var(--switch-bgDarkModeColor);

}

 

.switch [type="checkbox"]:focus + label span:first-child {

  box-shadow: 0 3px 5px rgba(255, 255, 255, 0.25);

}

 

.switch [type="checkbox"]:checked + label span:first-child::before {

  transform: translateX(24px);

}

 

.switch [type="checkbox"]:checked + label span:first-child::after {

  left: 12px;

  width: 15px;

  height: 15px;

  background: transparent;

  box-shadow: -2px -5px 0 var(--switch-moonColor);

  transform: translateY(-50%) rotate(-72deg);

}

页面内容样式

请记住,该 .page-content 部分包含两个子部分。

此部分将放置在距视口左侧 220 像素的位置。另外,我们会给它width: calc(100% - 220px)。请注意,它的 left属性值等于标题宽度。

它的风格:

/*CUSTOM VARIABLES HERE*/

 

.page-content {

  position: relative;

  left: var(--page-header-width);

  width: calc(100% - var(--page-header-width));

  min-height: 100vh;

  padding: 30px;

  color: var(--page-content-txtColor);

  background: var(--page-content-bgColor);

}

搜索和用户样式

另外,请记住该 .search-and-user 部分包含两个元素:搜索表单和.admin-profile.

为了布置它,我们将使用 CSS Grid。搜索表单将覆盖整个可用空间,并且在它和它的兄弟之间会有 50px 的间隙。两个兄弟姐妹将垂直对齐。

表单内的提交按钮将被绝对定位。它只包含一个装饰图标,因此我们需要一个 ARIA 属性来允许屏幕阅读器对其进行解释,从而使其可访问。

.admin-profile包含两个元素的 ,将表现为一个具有垂直居中内容的 flex 容器。 徽章(计数器)元素将绝对定位在其父元素内,内容水平和垂直居中。

以下是本节所需样式的一部分:

/*CUSTOM VARIABLES HERE*/

 

.search-and-user {

  display: grid;

  grid-template-columns: 1fr auto;

  grid-column-gap: 50px;

  align-items: center;

  background: var(--page-content-bgColor);

  margin-bottom: 30px;

}

 

.search-and-user form {

  position: relative;

}

 

.search-and-user form button {

  position: absolute;

  top: 50%;

  right: 15px;

  transform: translateY(-50%);

}

 

.search-and-user .admin-profile {

  display: flex;

  align-items: center;

}

 

.search-and-user .admin-profile .notifications {

  position: relative;

}

 

.search-and-user .admin-profile .badge {

  display: flex;

  align-items: center;

  justify-content: center;

  position: absolute;

  top: -10px;

  right: -3px;

  width: 18px;

  height: 18px;

  border-radius: 50%;

  font-size: 10px;

  color: var(--white);

  background: var(--red);

}

网格样式

为了在我们的管理仪表板上布置文章,我们将利用 CSS Grid。我们将为所有文章提供 300 像素的固定高度。除了涵盖整个父宽度的第一篇和最后一篇文章外,所有其他文章都将成为两列布局的一部分。

相关样式:

/*CUSTOM VARIABLES HERE*/

 

.page-content .grid {

  display: grid;

  grid-template-columns: repeat(2, 1fr);

  grid-gap: 30px;

}

 

.page-content .grid > article {

  display: flex;

  height: 300px;

  background: var(--page-content-blockColor);

  border-radius: var(--border-radius);

  box-shadow: var(--box-shadow);

}

 

.page-content .grid > article:first-child,

.page-content .grid > article:last-child {

  grid-column: 1 / -1;

}

4. 切换标题

每次我们点击折叠/展开按钮,标题状态都会改变。如果它被展开,它将折叠(只留下菜单项的图标变体),反之亦然。 


使用CSS和JavaScript创建一个响应式管理仪表板布局  第7张


请记住,此功能仅适用于大于 767 像素的屏幕。对于较小的屏幕,我们的标题将有不同的布局,我们很快就会谈到。

在标题的折叠状态期间,body元素接收collapsed类。此时,会发生以下情况:

  • 标头缩小。它的宽度从 220px 变为 40px。

  • 作为对此的回应,该.page-content部分增长。具体来说,它的宽度从width: calc(100% - 220px)变为width: calc(100% - 40px)。另外,它的 left属性值变成了 40px 而不是 220px。

  • 徽标、菜单标题、菜单链接文本、明暗主题切换器和菜单按钮文本消失。

  • 切换按钮的aria-expanded和aria-label属性值被更新。另外,它的图标旋转了 180 度,所以它看起来像一个展开图标。

下面是实现此功能的 javaScript 代码:

const body = document.body;

const collapseBtn = document.queryselector(".admin-menu .collapse-btn");

const collapsedClass = "collapsed";

 

collapseBtn.addeventListener("click", function() {

  body.classList.toggle(collapsedClass);

  this.getAttribute("aria-expanded") == "true"

    ? this.setAttribute("aria-expanded", "false")

    : this.setAttribute("aria-expanded", "true");

  this.getAttribute("aria-label") == "collapse menu"

    ? this.setAttribute("aria-label", "expand menu")

    : this.setAttribute("aria-label", "collapse menu");

});

以及所有相关的样式:

/*CUSTOM VARIABLES HERE*/

 

@media screen and (min-width: 768px) {

  .collapsed .page-header {

    width: 40px;

  }

 

  .collapsed .page-header .admin-menu li > * {

    padding: 10px;

  }

 

  .collapsed .page-header .logo,

  .collapsed .page-header .admin-menu span,

  .collapsed .page-header .admin-menu .menu-heading {

    display: none;

  }

 

  .collapsed .page-header .admin-menu svg {

    margin-right: 0;

  }

 

  .collapsed .page-header .collapse-btn svg {

    transform: rotate(180deg);

  }

 

  .collapsed .page-content {

    left: 40px;

    width: calc(100% - 40px);

  }

}

5.切换主题开关

每次我们点击切换开关,仪表板颜色都会改变。


使用CSS和JavaScript创建一个响应式管理仪表板布局  第8张


请记住,最初将启用暗模式。但是,一旦光照模式激活,html元素就会接收到light-mode类。


使用CSS和JavaScript创建一个响应式管理仪表板布局  第9张


此类将更新/覆盖许多预定义 CSS 变量(尤其是颜色变量)的值,从而改变主题外观。

这是所需的 JavaScript 代码:

const html = document.documentElement;

const switchLabel = document.querySelector(".switch label");

const switchLabelText = switchLabel.querySelector("span:last-child");

const lightModeClass = "light-mode";

 

switchInput.addEventListener("input", function () {

  html.classList.toggle(lightModeClass);

  if (html.classList.contains(lightModeClass)) {

    switchLabelText.textContent = "Light";

  } else {

    switchLabelText.textContent = "Dark";

  }

});

以及相关的样式:

/*CUSTOM VARIABLES HERE*/

 

.light-mode {

  --page-header-bgColor: #f1efec;

  --page-header-bgColor-hover: #b9e4e0;

  --page-header-txtColor: #2c303a;

  --page-header-headingColor: #979595;

  --page-content-bgColor: #fff;

  --box-shadow: 0 0 10px -2px rgba(0, 0, 0, 0.25);

}

 

.light-mode .page-header .admin-menu a:hover,

.light-mode .page-header .admin-menu a:focus,

.light-mode .page-header .admin-menu button:hover,

.light-mode .page-header .admin-menu button:focus {

  color: var(--black);

}

 

.light-mode .page-header .logo svg,

.light-mode .page-header .admin-menu a:hover svg,

.light-mode .page-header .admin-menu a:focus svg,

.light-mode .page-header .admin-menu button:hover svg,

.light-mode .page-header .admin-menu button:focus svg {

  fill: var(--black);

}

 

.light-mode .switch [type="checkbox"]:focus + label span:first-child {

  box-shadow: 0 3px 5px rgba(0, 0, 0, 0.25);

}

 

@media screen and (max-width: 767px) {

  .light-mode .search-and-user .admin-profile svg {

    fill: var(--black);

  }

}

在页面加载时保持选定模式

但我们还没有完成!如果我们可以存储用户的主题偏好并在他们每次重新访问管理员时启用它,那就太好了。我们可以通过利用本地存储来实现这一点。


使用CSS和JavaScript创建一个响应式管理仪表板布局  第10张


让我们看一下处理这个逻辑的 JavaScript 代码:

...

 

if (localstorage.getItem("dark-mode") === "false") {

  html.classList.add(lightModeClass);

  switchInput.checked = false;

  switchLabelText.textContent = "Light";

}

 

switchInput.addEventListener("input", function () {

  if (html.classList.contains(lightModeClass)) {

    localStorage.setItem("dark-mode", "false");

  } else {

    localStorage.setItem("dark-mode", "true");

  }

});

prefers-color-scheme从这里开始,您可以使用CSS 媒体功能更深入地进行更复杂的假设。例如,如果用户没有选择任何模式,您可以显示尊重其操作系统偏好的模式。但是现在,让我们保持简单。

6.在管理菜单项上显示工具提示

此时,让我们为可折叠标题添加另一个新功能。

正如我们在上一节中讨论的,当标题折叠时,菜单链接的文本将消失。这意味着,此时,只有 SVG 图标可见。因此,让我们显示一个工具提示,让用户更好地了解每个链接的作用。

为此,每次将鼠标悬停在菜单链接(图标)上时,我们都会为其添加title属性,其值是其span文本。但同样,只有当标题折叠并且窗口宽度至少为 768 像素时才会发生这种情况。


使用CSS和JavaScript创建一个响应式管理仪表板布局  第11张


下面是相应的 JavaScript: 

const body = document.body;

const menuLinks = document.querySelectorAll(".admin-menu a");

const collapsedClass = "collapsed";

 

for (const link of menuLinks) {

  link.addEventListener("mouseenter", function () {

    if (

      body.classList.contains(collapsedClass) &&

      window.matchMedia("(min-width: 768px)").matches

    ) {

      const tooltip = this.querySelector("span").textContent;

      this.setAttribute("title", tooltip);

    } else {

      this.removeAttribute("title");

    }

  });

}

7. 响应迅速

在最大 767px 宽的屏幕上,我们的页面将如下所示:


使用CSS和JavaScript创建一个响应式管理仪表板布局  第12张


这与我们的侧边栏安排有很大不同,对吧?让我们强调一下与桌面版本相比最重要的区别:

  • header 和 .page-content have position: static 和 width: 100%.

  • 元素的弯曲方向 nav 从 column 变为 row。

  • 移动菜单切换按钮变为可见。

  • 菜单绝对位于标题下方,最初是隐藏的。每次我们单击切换按钮时,它都会变得可见。 

  • 折叠/展开按钮和.greeting 元素被隐藏。

  • 该 .search-and-user 部分绝对定位并放置在移动菜单切换按钮旁边。 

下面你可以看到部分响应式样式:

@media screen and (max-width: 767px) {

  .page-header,

  .page-content {

    position: static;

    width: 100%;

  }

 

  .page-header nav {

    flex-direction: row;

  }

 

  .page-header .toggle-mob-menu {

    display: block;

  }

 

  .page-header .admin-menu {

    position: absolute;

    left: 98px;

    top: 57px;

    margin-top: 0;

    z-index: 2;

    border-radius: var(--border-radius);

    background: var(--page-header-bgColor);

    visibility: hidden;

    opacity: 0;

    transform: scale(0.95);

    transition: all 0.2s;

  }

   

  .page-header .admin-menu li:last-child button,

  .search-and-user .admin-profile .greeting {

    display: none;

  }

 

  .search-and-user {

    position: absolute;

    left: 131px;

    top: 10px;

    padding: 0;

    grid-column-gap: 5px;

    width: calc(100% - 141px);

    border-radius: var(--border-radius);

    background: transparent;

  }

}

8. 切换移动菜单

每次我们点击切换按钮,菜单状态都会改变。如果它被扩展,它会崩溃,反之亦然。


使用CSS和JavaScript创建一个响应式管理仪表板布局  第13张


在菜单的展开状态期间,body元素接收mob-menu-opened 类。此时,会发生以下情况:

  • 出现菜单。

  • 切换按钮的 aria-expanded 和 aria-label属性值被更新。另外,它的图标旋转了 180 度,所以它看起来像一个展开图标。

这是所需的 JavaScript 代码:

const body = document.body;

const toggleMobileMenu = document.querySelector(".toggle-mob-menu");

 

toggleMobileMenu.addEventListener("click", function() {

  body.classList.toggle("mob-menu-opened");

  this.getAttribute("aria-expanded") == "true"

    ? this.setAttribute("aria-expanded", "false")

    : this.setAttribute("aria-expanded", "true");

  this.getAttribute("aria-label") == "open menu"

    ? this.setAttribute("aria-label", "close menu")

    : this.setAttribute("aria-label", "open menu");

});

以及相关的 CSS:

.page-header .toggle-mob-menu svg {

  transition: transform 0.2s;

}

 

.page-header .admin-menu {

  transition: all 0.2s;

}

 

.mob-menu-opened .toggle-mob-menu svg {

  transform: rotate(180deg);

}

 

.mob-menu-opened .page-header .admin-menu {

  transform: scale(1);

  visibility: visible;

  opacity: 1;

}

结论

就是这样,伙计们!我们成功构建了一个功能齐全的管理仪表板布局。您将能够在此基础上进行扩展以创建各种管理界面。希望您和我一样享受这次旅程!


文章目录
  • 管理仪表板演示
  • 1. 从页面标记开始
    • SVG 精灵
    • 标题
    • 部分
    • 第 1 节
      • 第 2 节
  • 2. 定义一些基本样式
  • 3. 定义主仪表板样式
    • 样式标题
    • 菜单样式
    • 切换深色和浅色主题
    • 页面内容样式
      • 搜索和用户样式
      • 网格样式
  • 4. 切换标题
  • 5.切换主题开关
    • 在页面加载时保持选定模式
  • 6.在管理菜单项上显示工具提示
  • 7. 响应迅速
  • 8. 切换移动菜单
  • 结论