我始终很喜爱标签云,我喜爱通过看标签的绝对字体大小来理解网站上最受欢迎的标签是哪些,受欢迎的标签更大。

制作标签云有多艰难?一点也不难。让咱们来看看!

让咱们从HTML开始

对于咱们的HTML,咱们将每个标签放入<ul class=“tags”><ul> 列表中,咱们将应用JavaScript进行注入。

我模拟出了一些JSON,每个属性都有肯定数量的文章标签。让咱们写一些JavaScript来获取JSON feed并做三件事。

首先,咱们将从列表的每个条目中创立一个 <li>。设想一下,到目前为止,HTML是这样的:

<ul class="tags">  <li>align-content</li>  <li>align-items</li>  <li>align-self</li>  <li>animation</li>  <li>...</li>  <li>z-index</li></ul>

其次,咱们将每个属性的文章数放在每个列表项旁边的括号中。所以当初,标记是这样的:

<ul class="tags">  <li>align-content (2)</li>  <li>align-items (2)</li>  <li>align-self (2)</li>  <li>animation (9)</li>  <li>...</li>  <li>z-index (4)</li></ul>

第三,也是最初,咱们将在每个标记四周创立一个链接,该链接将达到正确的地位。在这里,咱们能够为每个我的项目设置 font-size 属性,这取决于该属性标记了多少篇文章。

<li class="tag">  <a    class="tag__link"    href="https://example.com/tags/animation"    style="font-size: 5em">    animation (9)  </a></li>

JavasScript局部

让咱们看一下执行此操作的JavaScript。

const dataURL =  "https://gist.githubusercontent.com/markconroy/536228ed416a551de8852b74615e55dd/raw/9b96c9049b10e7e18ee922b4caf9167acb4efdd6/tags.json";const tags = document.querySelector(".tags");const fragment = document.createDocumentFragment();const maxFontSizeForTag = 6;fetch(dataURL)  .then(function (res) {    return res.json();  })  .then(function (data) {    // 1. 从数据创立新数组    let orderedData = data.map((x) => x);    // 2. 按每个标签具备的文章数进行排序    orderedData.sort(function(a, b) {      return a.tagged_articles.length - b.tagged_articles.length;    });    orderedData = orderedData.reverse();    // 3. 获取蕴含最多文章的标签的值    const highestValue = orderedData[0].tagged_articles.length;    // 4. 为数据中的每个后果创立一个列表项    data.forEach((result) => handleResult(result, highestValue));    // 5. 将标签的残缺列表追加到tags元素    tags.appendChild(tag);  });

下面的JavaScript应用 Fetch API来获取 tags.json 所在的URL。在这里,咱们插入一个名为 orderedData 的新数组(这样咱们就不会更改原始数组),找到蕴含最多文章的标签。咱们将在稍后的 font-size 中应用这个值,这样所有其余标签都将有一个绝对于它的 font-size。而后,forEach 后果在响应中,咱们调用一个名为 handleResult() 的函数,并将 resulthighestValue 作为参数传递给该函数。它还会创立:

  • 一个称为 tags 的变量,这是咱们将用来注入从后果中创立的每个列表项的变量
  • 一个 fragment 的变量,用于保留循环的每次迭代的后果,咱们稍后将其附加到 tags,以及
  • 一个最大字体大小的变量,稍后将在字体比例中应用。

接下来,handleResult(result) 函数:

function handleResult(result, highestValue) {  const tag = document.createElement("li");  tag.classList.add("tag");  tag.innerHTML = `<a class="tag__link" href="${result.href}" style="font-size: ${result.tagged_articles.length * 1.25}em">${result.title} (${result.tagged_articles.length})</a>`;  // 将每个标签附加到片段 fragment  fragment.appendChild(tag);}

这是一个非常简单的函数,它能够创立一个列表元素,并将其设置为名为 tag 的变量,而后为这个列表元素增加一个 .tag 类。创立结束后,它将列表项的 innerHTML 设置为链接,并应用JSON Feed中的值(例如,指向标记的链接的 result.href)填充该链接的值。当每个 li 被创立后,它将作为一个字符串增加到 fragment 中,咱们稍后将把它追加到 tags 变量中。这里最重要的一项是内联款式标签,它应用文章数量--result.tagged_articles.length--为这个列表项设置一个应用 em 单位的绝对字体大小。稍后,咱们将把这个值改成一个公式来应用根本的字体比例。

我发现此JavaScript有点难看且难以了解,因而让咱们为咱们的每个属性创立一些变量和一个简略的字体比例公式,以整顿并使其更易于浏览。

function handleResult(result, highestValue) {  // 设置咱们的变量  const name = result.title;  const link = result.href;  const numberOfArticles = result.tagged_articles.length;  let fontSize = numberOfArticles / highestValue * maxFontSizeForTag;  fontSize = +fontSize.toFixed(2);  const fontSizeProperty = `${fontSize}em`;  // 为每个标签创立一个列表元素,并内联字体大小  const tag = document.createElement("li");  tag.classList.add("tag");  tag.innerHTML = `<a class="tag__link" href="${link}" style="font-size: ${fontSizeProperty}">${name} (${numberOfArticles})</a>`;    // 将每个标签附加到fragment  fragment.appendChild(tag);}

通过在创立HTML之前设置一些变量,能够使代码更容易浏览。而且这也让咱们的代码更DRY一些,因为咱们能够在多个中央应用 numberOfArticles 变量。

在此 .forEach 循环中返回了每个标签之后,它们将一起收集在 fragment 中。之后,咱们应用 appendChild() 将它们增加到 tags 元素中。这意味着DOM只被操作一次,而不是每次循环运行时都被操作,如果咱们碰巧有大量的 tags,这是一个不错的性能晋升。

字体缩放

咱们当初领有的就能够很好地工作了,咱们能够开始编写CSS了。然而,咱们的 fontSize 变量公式意味着领有最多文章的标签(也就是 25 篇文章的 "flex")将是 6em (25 / 25 6 = 6),但只有一篇文章的标签将是其大小的 1/25 (1 / 25 6 = 0.24),使得内容无奈浏览。如果咱们有一个有100篇文章的标签,那么较小的标签就会更蹩脚(1 / 100 * 6 = 0.06)。

为了解决这个问题,我增加了一个简略的 if 语句,如果返回的 fontSize 小于1,则将fontSize设置为1。当初,所有标签的字体范畴为1em至6em,四舍五入到小数点后两位。要减少最大标签的大小,只需更改 maxFontSizeForTag 的值即可。你能够依据你解决的内容数量来决定什么最适宜你。

function handleResult(result, highestValue) {  // 设置咱们的变量  const numberOfArticles = result.tagged_articles.length;  const name = result.title;  const link = result.href;  let fontSize = numberOfArticles / highestValue * maxFontSizeForTag;  fontSize = +fontSize.toFixed(2);    // 确保咱们的字体大小至多为1em  if (fontSize <= 1) {    fontSize = 1;  } else {    fontSize = fontSize;  }  const fontSizeProperty = `${fontSize}em`;    // 而后,为每个标签创立一个列表元素,并内联字体大小。  tag = document.createElement("li");  tag.classList.add("tag");  tag.innerHTML = `<a class="tag__link" href="${link}" style="font-size: ${fontSizeProperty}">${name} (${numberOfArticles})</a>`;  // 将每个标签附加到fragment  fragment.appendChild(tag);}

编写CSS!

咱们将 flexbox 用于布局,因为每个标签的宽度都能够变动。而后,咱们将它们与 justify-content: center,并删除列表我的项目符号。

.tags {  display: flex;  flex-wrap: wrap;  justify-content: center;  max-width: 960px;  margin: auto;  padding: 2rem 0 1rem;  list-style: none;  border: 2px solid white;  border-radius: 5px;}

咱们还将为单个标签应用flexbox。这样咱们就能够用 align-items: center 来垂直对齐,因为它们会依据字体大小而有不同的高度。

.tag {  display: flex;  align-items: center;  margin: 0.25rem 1rem;}

标签云中的每一个链接都有一点点的填充,只是为了让它在严格的尺寸之外能够略微点击。

.tag__link {  padding: 5px 5px 0;  transition: 0.3s;  text-decoration: none;}

我发现这在小屏幕上十分不便,特地是对于那些可能很难点击链接的人。最后的 text-decoration 被删除了,因为我认为咱们能够假如标签云中的每一条文字都是一个链接,所以不须要对它们进行非凡的装璜。

我将增加一些色彩,以使款式更加好看:

.tag:nth-of-type(4n+1) .tag__link {  color: #ffd560;}.tag:nth-of-type(4n+2) .tag__link {  color: #ee4266;}.tag:nth-of-type(4n+3) .tag__link {  color: #9e88f7;}.tag:nth-of-type(4n+4) .tag__link {  color: #54d0ff;}

这个配色计划是间接从Chris’ blogroll偷来的,从标签1开始的每四个标签是黄色的,从标签2开始的每四个标签是红色的,从标签3开始的每四个标签是紫色的。

而后,咱们为每个链接设置焦点和悬停状态:

.tag:nth-of-type(4n+1) .tag__link:focus,.tag:nth-of-type(4n+1) .tag__link:hover {  box-shadow: inset 0 -1.3em 0 0 #ffd560;}.tag:nth-of-type(4n+2) .tag__link:focus,.tag:nth-of-type(4n+2) .tag__link:hover {  box-shadow: inset 0 -1.3em 0 0 #ee4266;}.tag:nth-of-type(4n+3) .tag__link:focus,.tag:nth-of-type(4n+3) .tag__link:hover {  box-shadow: inset 0 -1.3em 0 0 #9e88f7;}.tag:nth-of-type(4n+4) .tag__link:focus,.tag:nth-of-type(4n+4) .tag__link:hover {  box-shadow: inset 0 -1.3em 0 0 #54d0ff;}

我兴许能够在这个阶段为色彩创立一个自定义变量,比方 --yellow: #ffd560 等,但为了反对IE 11,我还是决定采纳手写的办法。我喜爱 box-shadow 悬停成果,它只须要很大量的代码就能实现比规范的下划线或底边框更有视觉效果的货色。在这里应用 em 单位意味着咱们能够很好地管制暗影绝对于须要笼罩的文本的大小。

首先,将每个标记链接设置为悬停时为彩色:

.tag:nth-of-type(4n+1) .tag__link:focus,.tag:nth-of-type(4n+1) .tag__link:hover,.tag:nth-of-type(4n+2) .tag__link:focus,.tag:nth-of-type(4n+2) .tag__link:hover,.tag:nth-of-type(4n+3) .tag__link:focus,.tag:nth-of-type(4n+3) .tag__link:hover,.tag:nth-of-type(4n+4) .tag__link:focus,.tag:nth-of-type(4n+4) .tag__link:hover {  color: black;}

咱们实现了!这是最终后果: