OOCSS: Media & Flag Object
这一切都始于媒体对象(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),咱就不多说。用几张图来向大家阐述:
这样风格的在视交媒体网站上常能看到,甚至说在很多Web网站都能看到,特别是评论系统中。
根据上面示例图,很明显分为:
对于这样的布局,我们有些不确定的因素:
- 图片大小和对齐方式
- 右边内容不知
- 宽度未知
对于这样的布局,其实并不是复杂的,接下来我们简单的演示一下其实现过程:
<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也做了相应的处理,如下图所示:
记得在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还是存在一定的缺陷。