这一切都始于媒体对象(Media Object)。其实就是Nicole写的一个CSS代码片段,这个代码片段是常用来阐述OOCSS的最佳示例。
这篇文章能让你对媒体对象更佳的熟悉与了解,如果对媒体对象一点都不了解,建议你先点击这里了解一二。
面对需求
对于一位从事前端工作的人员,需求是不断的增加,而作为一名码农来说,又能如何的保持可持续、系统、灵活的满足我们平时工作中日益增长的项目需求。
We're not designing pages, we're designing systems of components——Stephen Hay
Modularity is a requirement of maintainable systems ——BenCallahan
实际工作中,我们的目标非常的简单。如何制作出可复用的代码,更快和更高效的样式,而且更易维护。
为了达到此目的,Nicole首次提出了OOCSS的思想。而OOCSS思想的原则非常的简单与明确:样式和结构的分离与容器和内容的分离。
样式与结构的分离
先来看一段简单的代码片段:
#button {
width: 200px;
height: 50px;
padding: 10px;
border: 1px solid #ccc;
background: linear-gradient(#ccc,#222);
box-shadow: 2px 2px 5px rgba(0,0,0,.5);
}
#box {
width: 400px;
overflow: hidden;
border: 1px solid #ccc;
background: linear-gradient(#ccc, #222);
box-shadow: 2px 2px 5px rgba(0,0,0,.5);
}
#widget {
width: 500px;
min-height: 200px;
overflow: auto;
border: 1px solid #ccc;
background: linear-gradient(#ccc, #222);
box-shadow: 2px 2px 5px rgba(0,0,0,.5);
}
纵观下来,#button
、#box
和#widget
都有一部分样式是相同的:
border: 1px solid #ccc;
background: linear-gradient(#ccc, #222);
box-shadow: 2px 2px 5px rgba(0,0,0,.5);
根据OOCSS的原则之一:结构与样式分离。可以将共用的皮肤样式定义为:
.skin {
border: 1px solid #ccc;
background: linear-gradient(#ccc, #222);
box-shadow: 2px 2px 5px rgba(0,0,0,.5);
}
元素#button
、#box
和#widget
可引用共用样式的类名.skin
。根据此原则,我们的结构相应可以修改为:
<button class="button skin"></button>
<div class="box skin"></div>
<div class="widget skin"></div>
如此一来,样式修改为:
.button {
width: 200px;
height: 50px;
padding: 10px;
}
.box {
width: 400px;
overflow: hidden;
}
.widget {
width: 500px;
min-height: 200px;
overflow: auto;
}
.skin {
border: 1px solid #ccc;
background: linear-gradient(#ccc, #222);
box-shadow: 2px 2px 5px rgba(0,0,0,.5);
}
容器与内容的分离
假设页面侧边栏标题有一段这样的样式:
#sidebar h3 {
font-family: arial,sans-serif;
font-size: .8em;
line-height: 1;
color: #777;
text-shadow: 3px 3px 6px rgba(0,0,0,.3);
}
除此之外,在别的地方标题也有相同的样式:
#footer h3 {
font-family: arial,sans-serif;
font-size: .8em;
line-height: 1;
color: #777;
text-shadow: 3px 3px 6px rgba(0,0,0,.3);
}
大家都知道,这样做是不明智的。那么根据OOCSS的原则,我们可以将内容和容器分开。那么将上面的样式提取:
.title {
font-family: arial,sans-serif;
font-size: .8em;
line-height: 1;
color: #777;
text-shadow: 3px 3px 6px rgba(0,0,0,.3);
}
简单的了解了OOCSS之后,我们回到话题中来。
媒体对像(Media Object)
什么是媒体对像(Media Object),咱就不多说。用几张图来向大家阐述:
Image may be NSFW.
Clik here to view.
Image may be NSFW.
Clik here to view.
Image may be NSFW.
Clik here to view.
Image may be NSFW.
Clik here to view.
这样风格的在视交媒体网站上常能看到,甚至说在很多Web网站都能看到,特别是评论系统中。
根据上面示例图,很明显分为:
Image may be NSFW.
Clik here to view.
对于这样的布局,我们有些不确定的因素:
- 图片大小和对齐方式
- 右边内容不知
- 宽度未知
对于这样的布局,其实并不是复杂的,接下来我们简单的演示一下其实现过程:
<div class="media">
<div class="media__object">
<img src="" alt="">
</div>
<div class="media__body">
...
</div>
</div>
添加点样式:
.media{
&:after {
content:"";
clear:both;
display:table;
}
&__object {
float: left;
}
&__body {
overflow: hidden;
}
}
其效果如下:
看上去并不漂亮。稍作修改一二:
<div class="media card">
<div class="media__object">
<img src="" alt="">
</div>
<div class="media__body">
...
</div>
</div>
.card {
border: 1px solid #ccc;
padding: 20px;
max-width: 50%;
margin: 20px auto;
.media__body {
padding-left: 20px;
}
}
你可以打开浏览器,收缩浏览器的大小,你可以看到其整个布局并不会造成错乱。
话说回来,虽然轻易的实现需要的效果。但也存在一定的缺陷。
- 图片对齐方式不好控制
- 如果图片搁置位置不同,需要修改结构
+---------+ ~~~~~~~~~~ ~~~~~
| | ~~~~~ ~~~~~ ~~~~
| | ~~~~~~~~~ ~~~~~~
| |
+---------+
虽然媒体对象很棒,但有一个扩展性不强:垂直对齐。通常图像和文本内容对齐的方式较为理想的是像这样:
+---------+
| | ~~~~ ~~~~~~~~~~~
| | ~~~~~~~ ~~~~~ ~~
| | ~~~~~~~~~~~~
+---------+
这种构造在实际工作中也是常见的一种需求,其表面上看起来很简单,但看到的只是外表,而这外表常常是骗人的。要实现上面的效果,唯一的方法就是在内容区域(.media__body
)上添加合适的padding
或margin
。
或许当初实现这样的效果会令CSSer头痛,你也会常跟需求方说,这样要实现起来并不是那么的简单。而到目前为止,实现起来相对而言会较为简单。
Flag Object
在介绍Flag Object实现这样的布局之前,我们还有Flexbox方法可以实现。在这里就不做过多的阐述,如果你感兴趣,可以点击这里了解有关于Flexbox相关知识。
接下来回到Flag Object上面,其实运用的原理很简单,就是模拟table
。那么将Media Object的结构做一个调整:
<div class="flag">
<div class="flag__item">
<img src="" alt="">
</div>
<div class="flag__item">
...
</div>
</div>
样式如下:
.flag {
display: table;
width: 100%;
&__item {
display: table-cell;
vertical-align: top;
> img {
display: block;
}
&--heading {
margin: 0;
+ p {
margin-top: 20px;
}
}
}
&__item + &__item {
padding-left: 20px;
}
}
在上面的示例上加点料:
.flag {
display: table;
width: 100%;
&__item {
display: table-cell;
.flag-top & {
vertical-align: top;
}
.flag-middle & {
vertical-align: middle;
}
.flag-bottom & {
vertical-align: bottom;
}
> img {
display: block;
}
&--heading {
margin: 0;
+ p {
margin-top: 20px;
}
}
}
&__item + &__item {
padding-left: 20px;
}
}
可以在flag
上添加类名,比如flag-top
,并且通过vertical-algin
来控制.flag__item
对齐方式。当然,我们也可以在.flag__item
上添加类名flag-top
设置vertical-align
。
上面虽然实现咱们需要的效果,但有时候在放置内容的区域还是会存在一定的问题。其实有一种简单的解决方案。就是在放置文本内容的flag__item
多添加一个类名flag__item--body
,并且在上面设置样式width: 100%
。在Bootstrap4中Media Object也做了相应的处理,如下图所示:
Image may be NSFW.
Clik here to view.
记得在Media Object中说过,如果内容右内则添加图片,或者别的内容,对结构也有一定的要求,但在Flag Object中可以自由扩展,如下面的示例:
Media Object 和 Flag Object不同之处
除了垂直对齐视觉上的差异之外,Media Object和Flag Object两个在代码上没有太多的区别。不过有一点需要注意的是,Flag Object在图片对象外需要添加一个容器。将两者代码放在一起做一个简单对比:
//Media Object
<div class="media">
<img class="media__object" src="" alt="" />
<div class="media__body">
...
</div>
</div>
//Flag Object
<div class="flag">
<div class="flag__item flag__item--image">
<img src="" alt="" />
</div>
<div class="flag__item flag__item--body">
...
</div>
</div>
总结
媒体对象是一个经典的运用了。如果不考虑对象垂直方向对齐方式来说,足够使用。对于Flag Object来说,虽解决了Media Object内容垂直方向对齐方式之外,还可以很轻意的扩展。只不过对于低版本的IE还是存在一定的缺陷。
如需转载,烦请注明出处:http://www.w3cplus.com/css/media-object-vs-flag-object.html