中间盒链接

Avatar of Chris Coyier
Chris Coyier on

DigitalOcean 为您的旅程的每个阶段提供云产品。 从 $200 免费积分开始!

有史以来最糟糕的名字,但我一直在努力给它命名,这似乎很合适。 这是最终结果

它涵盖了我认为有趣的一些内容

  • jQuery 1.4 的新元素创建语法,它非常酷,我们还没有介绍
  • 编写一个小型插件以防止重复代码(并保持 jQuery 的精神)
  • 谈到我开始考虑的面向对象的 CSS

目标

我们这里有一些内容框。 目标是当您将鼠标悬停在它们上时,它们会变暗,并且链接会出现在它们的正中心。 我意识到这对很多东西来说不是理想的 UI 选择。 使事物在您将鼠标悬停在它们上时变得不可读是一种不寻常的设计选择。 但在某些情况下它可能是完美的。 故事寓意:不要根据演示做出草率的判断。

HTML

只是一个包含一些文本的 div...

<div class="widget widget-one rounded">
  <p>Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Vestibulum tortor quam, feugiat vitae, ultricies eget, tempor sit amet, ante. Donec eu libero sit amet quam egestas semper. Aenean ultricies mi vitae est. Mauris placerat eleifend leo.</p>
</div>

可能想要做的是在每个小部件中包含一个超链接,该链接将指向与我们将在 JavaScript 中添加的链接相同的位置(可降级性)。 再次强调,这只是一个演示,在实际场景中情况会有所不同。

CSS

我称我们的小方框为“小部件”。 请注意,我为 div 包装器指定了一个名为 widget 的类。 这是基本的小部件

.widget { 
   width: 300px; 
   padding: 20px; 
   border: 1px solid #999;
   margin: 0 20px 20px 0;
   float: left; 
   position: relative; 
}

但请注意,在上面的实时演示和图像中,小部件具有圆角。 我们都知道如何在 CSS 中创建圆角。 存在标准border-radius以及它的姊妹供应商扩展。 为什么不直接将它们添加到 widget CSS 本身呢? 这就是面向对象的 CSS 的用武之地...

我的大脑和 CSS通常的工作方式是,我尝试使 HTML 尽可能干净和语义化。 我一直被教导说使用像“red”这样的 CSS 类名是一种非常糟糕的做法,因为“red”不是语义化的,是专门描述性的。 相反,您应该使用诸如“important”或“warning”之类的东西,因为如果您后来决定这些东西应该变成绿色而不是红色,那么您的“red”类就会令人尴尬地变得无关紧要。

面向对象的 CSS 颠覆了部分这种思维方式。 面向对象的 CSS 使用类名专门描述该“对象”(页面元素)的设计特征。 请注意,我还为小部件指定了一个名为“rounded”的类。 在我们的 CSS 中,rounded 类将是

.rounded { 
   -moz-border-radius: 20px;  
   -webkit-border-radius: 20px; 
   border-radius: 20px; 
}

亵渎神明? 我过去也这么认为,但最近我非常喜欢这种方法。 页面上可能有 20 件事是“rounded”的。 现在我们只需要将 rounded 类名应用到它们中的每一个,它们就会变成圆角。 需要调整边框半径吗? 在一个地方调整它,所有圆角对象都会匹配。 如果不这样做,我们将在 CSS 中更新 60 个不同的位置。

这可能适合某些站点,而不适合其他站点。 这感觉像是一个逃避责任的说法,但确实如此。 也许对于拥有大量遗留内容的站点来说,这并不现实。 它可能非常适合拥有较少内容的新站点,在那里 CSS 几乎和 HTML 一样多。

JavaScript 最终将向我们的 Widget 应用一个新的 div,该 div 的作用是使 Widget 变暗。 我们将这个类称为“overlay”。 以下是它的 CSS

.overlay { 
    position: absolute; top: 0; left: 0; right: 0; bottom: 0;
    background: url(../images/black75.png);
    background: rgba(0,0,0,0.6); 
    text-align: center; 
}

它使用 RGBa 为现代浏览器进行变暗(更灵活,可能会节省一个 HTTP 请求),并回退到一个 alpha 透明的 PNG(对于 IE 7)。 处理此问题的另一种方法是使用纯黑色背景颜色并使用常规透明度,但由于在该演示中我们将有“中间盒链接”位于叠加层内,并且我们不希望它也透明,因此这种方法效果很好。

jQuery JavaScript

快速重复一下我们的目标:当 Widget 被悬停时,我们希望将它变暗并在它的正中间添加一个链接。 在我们的演示中,我们有四个 Widget。 其中一些高度不同,因此我们需要对此进行调整。 每个 Widget 还显示不同的文本作为“中间按钮链接”,以及不同的 URL。 这意味着一些代码将不同,但很多代码会相同。 这需要进行一些抽象。 在 JavaScript 中,我们可以直接使用自定义函数,我们可以为每个 Widget 调用该函数。 但是,秉持 jQuery 的精神,让我们把它变成一个小插件。 这意味着我们将保持完整的 jQuery 特定功能,例如可链接性。

请注意,我们已经为每个 Widget 添加了一个唯一的类名。 这样我们就可以使用 JavaScript 中的该挂钩单独定位 Widget。 我们也可以使用 ID,这更有效率,但嘿,您可能在同一个页面上拥有两个使用相同文本和链接的 Widget。 使用相同的类名将在这种情况下有效,而 ID 则不会。 这是我们想要的抽象

$(function() {
    
    $(".widget-one").middleBoxButton("Read More", "#read");
    $(".widget-two").middleBoxButton("Go to the Store", "#store");
    $(".widget-three").middleBoxButton("Continue", "#more");
    $(".widget-four").middleBoxButton("Behold!", "#bazinga");

});

当然,“middleBoxButton”不是一个函数。 这正是我们要作为插件创建的。 以下是整个代码

var $el, $tempDiv, $tempButton, divHeight = 0;

$.fn.middleBoxButton = function(text, url) {
    
    return this.hover(function(e) {
    
        $el = $(this).css("border-color", "white");
        divHeight = $el.height() + parseInt($el.css("padding-top")) + parseInt($el.css("padding-bottom"));
                
        $tempDiv = $("<div />", {
            "class": "overlay rounded"
        });
        
        $tempButton = $("<a />", {
            "href": url,
            "text": text,
            "class": "widget-button rounded",
            "css": {
                top: (divHeight / 2) - 7 + "px"
            }
        }).appendTo($tempDiv);
        
        $tempDiv.appendTo($el);
        
    }, function(e) {
    
        $el = $(this).css("border-color", "#999");
    
        $(".overlay").fadeOut("fast", function() {
            $(this).remove();
        })
    
    });
    
}

因此,当 Widget 被悬停时,会创建一个全新的<div>。 此 div 具有“overlay”和“rounded”类。 我们已经知道“rounded”是什么意思(OOCSS)。 我们也已经知道“overlay”是什么,它确保 div 的大小与 div 完全相同,方法是设置绝对定位以及将顶部、右侧、底部和左侧值都设置为零,并处理变暗。 但是,此时还没有对这个 div 进行任何操作。

然后我们创建一个锚链接。 我们赋予它文本和 href 属性,这些属性是我们为此目的显式传递给插件的。 然后我们将此链接附加到我们刚刚创建的 overlay div,然后将它们都附加到 Widget。 jQuery 1.4 的新元素创建语法使这个元素创建过程变得非常简洁。 这部分

$("<a />", {
    "href": url,
    "text": text,
    "class": "widget-button rounded",
    "css": {
        "top": (divHeight / 2) - 7 + "px"
    }
});

请注意,我将所有“键”(冒号之前的部分)都放在引号中。 大多数键在没有引号的情况下也能正常工作,但我遇到了 key “class” 在 IE 中无法正常工作的问题。 事实证明这不是一个 bug,只是“class”是 JavaScript 中的保留字,而且不加引号的做法是不好的。 事实证明,在使用像这样使用的类似 JSON 的语法时,对所有内容都加引号是好的做法。

由于我们的目标之一是链接出现在正中间,所以让我们来谈谈它。 水平居中很容易,overlay div 具有 text-align: center,所以这就完成了。 垂直居中有点棘手。 有 CSS 方法可以处理它,但没有一种方法是超级干净和简单的。 我们已经在使用 JavaScript 了,所以让我们利用它。 我们将测量 Widget 的高度,将其减半,并将链接向下移动该距离。 唯一有点笨拙的地方是值“7”。 您一定讨厌在硬编码这样的值的时候,实际上我的意思是“按钮高度的一半”。 问题是,当我设置其他属性时,我无法计算按钮的高度,因为它还不存在。 如果您有想法,请告诉我。 还要注意,Widget 的高度不是仅仅使用 .height() 函数计算出来的,而是通过使用该函数并添加顶部和底部填充来计算出来的。

悬停(鼠标移出)的回调函数只是将边框恢复为其原始颜色,并淡出(然后移除)overlay div。 完成!

演示和下载

查看演示   下载文件