Scalable and Modular Architecture
CSS and JavaScript
Simplicity is the ultimate sophistication.
Leonardo da Vinci
ME
• Christian Tusborg
When CSS is wrong
body.dark #comCustomizer .top .color-changer > div ul li a:active span
.com.product-slider .viewport > ul > li > div .name h3
.com.product-slider .viewport > ul > li > div ul.colors li + li
.warp.product-slider .viewport > ul > li > div ul.colors li + li
.com.product-slider .viewport > ul > li > div .image div img
.oldTemplate .com.product-slider .viewport > ul
.com .expandable-area .cart .items ul li.count > *
.com .expandable-area .cart .items ul li.count input
.com .expandable-area .compare .items ul li div.image > div
#page-content .com.product-slider .viewport > ul
#page-content .com.product-slider .viewport > ul > li #Link div.cta
When CSS is wrong
body.dark .com .white h2,
body.dark .com.white h2,
body.dark .com .white h3,
body.dark .com.white h3,
body.dark .com .white h4,
body.dark .com.white h4,
body.dark .com .white h5,
body.dark .com.white h5,
body.dark .jabecom .white h6,
body.dark .jabecom.white h6 {
color: #1a1a1a;
}
When JavaScript is wrong
knockout-2.3.0.min.js
QsgImageField.js
sc-webforms-support.js
sc.webforms.js
LazyLoadImg.js
jquery-1.7.1.js
app-viewmodel.js
chosen.jquery.min.js
jquery.lazyload.js
custom-ko-bindings.js
jquery-ui-i18n.js
jquery-ui.min.js
jquery.ba-hashchange.js
jquery.bez.js
jquery.cookie.js
jquery.easing.1.3.js
jquery.isotope.js
jquery.shortcuts.min.js
jquery.showLoading.js
knockout.mapping.js
knockout.validation.js
navigation.js
product-filtering.js
reveal-menu.js
tiny-table.js type-ahead.js
yass.js
jquery.datepicker.js
jquery.details.min.js
smooth-scroll.js
youtube.js fd-slider.min.js
jquery.sticky.js knockout-2.1.0.js
modernizr.custom.10605.js fd-slider.js
spinner.js sugar-1.2.5-custom.development.js
When JavaScript is wrong
Total: 1,473 MB
On every page!!!
Oh wait this ONLY library
We did forget the 0,493 MB of custom JavaScript
1,966 MB JavaScript
CSS 0,371 MB
How do we end up there?
Having lots of consult adding code.
Having no naming convention.
Having no over all plan.
Having short time line for projects.
How do we end up there?
Having lots of consult adding code.
Having no naming convention.
Having no over all plan.
Having short time line for projects.
How to solve?
Think little goals and expect little achievements. Think big goals and win big
success.
- David Joseph Schwartz
How to solve?
I'm not the smartest fellow in the world, but I can sure pick smart colleagues.
- Franklin D. Roosevelt
Who is my smart colleagues?
John Resig, Douglas Crockford, Dean Edwards, Nicholas C. Zakas
Dustin Diaz, Paul Irish, Juriy Zaytsev, Stoyan Stefanov, Lucas Smith
Addy Osmani, Jens Roland
The page I look for ideas:
http://yahoo.com
http://facebook.com
http://google.com
http://yandex.ru
http://twitter.com
BEM. Block, Element, Modifier
The BEM methodology was developed at Yandex.
•
•
•
•
•
Standard projects should be developed fast and the results last long: a product created in a short time, built on an architecture that ensures its maintainability and
longevity for years.
A project involves many people. The ability to efficiently organize people’s work in a team is important, whether it’s a team of two or dozens of developers.
Scalable teams. Adding more people to a team should improve the team’s performance. A process must be in place that ensures that new developers are brought up
to speed quickly and are duly allocated their specific areas of responsibility. Code must be carefully structured to ensure its maintainability over time and through
team changes.
Code reuse. Each new project or interface element should not be started from scratch. Code reuse between similar tasks should be maximized within the company.
Code should not be context-dependent but be easily transferable to different contexts.
We were trying to find solutions to our problems. The solutions we found eventually became the BEM methodology.
BEM. Block, Element, Modifier
• https://bem.info/method/
• http://csswizardry.com/2013/01/mindbemding-getting-your-head-roundbem-syntax/
BEM. Block, Element, Modifier
The naming convention follows this pattern:
block {}
.block__element {}
.block--modifier {}
.block represents the higher level of an abstraction or component.
.block__element represents a descendent of .block that helps form .block as a whole.
BEM. Block, Element, Modifier
The naming convention follows this pattern:
.site-search {} /* Block */
.site-search__field {} /* Element */
.site-search--full {} /* Modifier */
BEM. Block, Element, Modifier
.person {}
.person__hand {}
.person--female {}
.person--female__hand {}
.person__hand--left {}
BEM. Block, Element, Modifier
<form class="site-search full">
<input type="text" class="field">
<input type="Submit" value ="Search" class="button">
</form>
<form class="site-search site-search--full">
<input type="text" class="site-search__field">
<input type="Submit" value ="Search" class="site-search__button">
</form>
BEM. Block, Element, Modifier
<div class="social-media">
<ul class="social-media__list">
<li class="social-media__list__item social-media__list__item--google">
<a class="social-media__list__item_link social-media__list__item--google__link" href="javascript:void(0)">
<i class="social-media__list__item___link__icon social-media__list__item--google__link__icon">
Google+
</i>
</a>
</li>
<li class="social-media__list__item social-media__list__item--twitter">
<a class="social-media__list__item_link social-media__list__item--twitter__link" href="javascript:void(0)">
<i class="social-media__list__item__link__icon social-media__list__item___link__icon social-media__list__item--twitter__link__icon">
Twitter
</i>
</a>
</li>
</ul>
</div>
BEM. Block, Element, Modifier
<div class="social-media">
<ul class="social-media__list">
<li class="social-media__item social-media__item--google">
<a class="social-media__link social-media---google__link" href="javascript:void(0)">
<i class="social-media__icon social-media--google__link__icon">
Google+
</i>
</a>
</li>
<li class="social-media__list__item social-media__list__item--twitter">
<a class="social-media__list__item_link social-media__list__item--twitter__link" href="javascript:void(0)">
<i class="social-media__list__item__link__icon social-media__list__item___link__icon social-media__list__item--twitter__link__icon">
Twitter
</i>
</a>
</li>
</ul>
</div>
.site-search {} /* Block */ .site-search__field {} /* Element */ .site-search--full {} /* Modifier */
BEM. Block, Element, Modifier with a twist of
SMACSS
<div class="social-media">
<ul class="social-media__list">
<li class="social-media__list__item social-media__list__item--google">
<a class="social-media__list__item_link social-media__list__item--google__link" href="javascript:void(0)">
<i class="social-media__list__item___link__icon social-media__list__item--google__link__icon">
Google+
</i>
</a>
</li>
<li class="social-media__list__item social-media__list__item—twitter is-social-media__list__item--hidden">
<a class="social-media__list__item_link social-media__list__item--twitter__link" href="javascript:void(0)">
<i class="social-media__list__item__link__icon social-media__list__item___link__icon social-media__list__item--twitter__link__icon">
Twitter
</i>
</a>
</li>
</ul>
</div>
BEM. Block, Element, Modifier with a twist of
SMACSS
Base Rules
Layout Rules
Module Rules (Replaced with BEM)
State Rules
Theme Rules
BEM. Block, Element, Modifier with a twist of
SMACSS
Base Rules:
A Base rule is applied to an element using an element selector, a descendent
selector, or a child selector, along with any pseudo-classes. It doesn’t include
any class or ID selectors. It is defining the default styling for how that element
should look in all occurrences on the page.
body, form {
margin: 0;
padding: 0;
}
BEM. Block, Element, Modifier with a twist of
SMACSS
Layout Rules:
CSS, by its very nature, is used to lay elements out on the page. However,
there is a distinction between layouts dictating the major and minor
components of a page. The minor components—such as a callout, or login
form, or a navigation item—sit within the scope of major components such as
a header or footer. I refer to the minor components as Modules and will dive
into those in the next section. The major components are referred to as Layout
styles.
BEM. Block, Element, Modifier with a twist of
SMACSS
Layout Rules:
#header, #article, #footer {
width: 960px;
margin: auto;
}
#article
{
border-width: 1px 0 0;
}
#article {
float: left;
}
#sidebar {
float: right;
} .l-flipped #article {
float: right;
}
.l-flipped #sidebar {
float: left;
}
BEM. Block, Element, Modifier with a twist of
SMACSS
State Rules:
A state is something that augments and overrides all other styles. For example, an accordion section may be in
a collapsed or expanded state. A message may be in a success or error state.
States are generally applied to the same element as a layout rule or applied to the same element as a base
module class.
<div id="header" class="is-collapsed">
<form>
<div class="msg is-error">
There is an error!
</div>
<label for="searchbox" class="is-hidden">Search</label>
<input type="search" id="searchbox">
</form>
</div>
BEM. Block, Element, Modifier with a twist of
SMACSS
State Rules:
Using !important
States should be made to stand alone and are usually built of a single class selector.
Since the state will likely need to override the style of a more complex rule set, the
use of !important is allowed and, dare I say, recommended. (I used to say that
!important was never needed but on complex systems, it is often a necessity.) You
won’t normally have two states applied to the same module or two states that tend to
affect the same set of styles, so specificity conflicts from using !important should be
few and far between.
With that said, be cautious. Leave !important off until you actually and truly need it
(and you will see why in this next example). Remember, the use of !important should
be avoided for all other rule types. Only states should have it.
BEM. Block, Element, Modifier with a twist of
SMACSS
State Rules:
.tab {
background-color: purple;
color: white;
}
.is-tab-active {
background-color: white;
color: black;
}
BEM. Block, Element, Modifier with a twist of
SMACSS
Theme Rules:
Theme Rules aren't as often used within a project and because of that, they aren't included as
part of the core types. Some projects may have a need for them.
// in module-name.css
.mod {
border: 1px solid;
}
// in theme.css
.mod {
border-color: blue;
}
BEM. Block, Element, Modifier with a twist of
File:
SMACSS
module-name/
module-name.ascx
less/
module-name.less
media/
module-name--media.less
theme/
module-name--default.less
state/
module-name--state.less
js/
module-name.js
JavaScript
15 KB of JavaScript is all you when load the page.
25KB of JavaScript covers 80% of all you really do on the page.
JavaScript - Hypothesis
All we Do is:
Append data.
Replace data.
Remove data.
Submit from.
Show dialog.
Search
Animation affects
JavaScript – One click function only
document.documentElement.addEventListener('click', function (evt) {
var element;
evt.srcElement ? element = evt.srcElement : element = evt.target;
if (!(hlr = element.getAttribute('x-hlr'))) {
return;
}
evt.preventDefault();
if (hlr == "PreventDefault") {
return;
}
window.co.hlr(element);
}, false);
JavaScript – One click function only
window.co = window.co || {};
window.co.hlr = function (element) {
var hlr;
if (!(hlr = element.getAttribute('x-hlr'))) {
return;
}
if (hlr == "PreventDefault") {
return;
}
var splitArray = element.getAttribute('x-hlr').split(' ');
for (var i = 0, items = splitArray.length; i < items; i++) {
hlr = splitArray[i];
if (window.co.fn[hlr]) {
window.co.fn[hlr](element);
}
}
};
window.co = window.co || {};
JavaScript – Dialog
window.co.fn = window.co.fn || {};
window.co.fn.Dialog = function (elm) {
var dialogAct = elm.getAttribute("x-DialogAct");
if (window.co.fn.Dialog[dialogAct]) {
window.co.fn.Dialog[dialogAct](elm);
}
};
window.co.fn.Dialog.Show = function (elm) {
jQuery(".modalOverlay-header").html(document.getElementById(elm.getAttribute("x-DialogHeader")).innerHTML);
jQuery(".modalOverlay-body").html(document.getElementById(elm.getAttribute("x-DialogBody")).innerHTML);
jQuery(".modalOverlay-footer").html(document.getElementById(elm.getAttribute("x-DialogFooter")).innerHTML);
jQuery(".modalOverlay-black").show();
};
window.co.fn.Dialog.Close = function (elm) {
jQuery(".modalOverlay-black").hide();
};
window.co.fn.Dialog.init = function () {
};
window.co.fn.Dialog.init();
JavaScript – Open dialog using html
<script id=“MyHeader” type=“text/html”>
Something for Header
</script>
<script id=“MyBody” type=“text/html”>
Something for Body
</script>
<script id=“Myfooter” type=“text/html”>
Something for Footer
</script>
<button x-hlr=“Dialog” x-DialogAct=“Show” x-DialogHeader=”MyHeader” x-DialogBody=”MyBody” x-DialogFooter=”MyFooter”>Open Dialog</button>
JavaScript – Open dialog using JavaScript
var elm = document.createElement("a");
elm.setAttribute("x-hlr", “Dialog");
elm.setAttribute(" x-DialogAct ", “Show");
elm.setAttribute(" x-DialogHeader ", "MyHeader");
elm.setAttribute(" x-DialogBody ", "MyBody");
elm.setAttribute(" x-DialogFooter ", "MyFooter ");
Window.co.hlr(elm);
JavaScript – AMD
Asynchronous module definition (AMD) is a JavaScript API for defining
modules such that the module and its dependencies can be asynchronously
loaded. It is useful in improving the performance of websites by bypassing
synchronous loading of modules along with the rest of the site content.
In addition to loading multiple JavaScript files at runtime, AMD can be used
during development to keep JavaScript files encapsulated in many different
files. This is similar to other programming languages, like Java, which support
keywords such as import, package, and class for this purpose. It is then
possible to concatenate and minify all the source JavaScript into one small file
used for production deployment.
JavaScript – Bootloader
curl(['js/Dialog'], function (m) {
m(element);
});
JavaScript – Bootloader
define(['js/Append'], function () {
var exports = {};
window.co.fn.append = function (element) {
var target = document.getElementById(element.getAttribute("x-AppendTarget"));
var payload = document.getElementById(element.getAttribute("x-AppendTarget”));
if (target == null || payload == null) {
return;
}
target.innerHTML += payload.innerHTML
};
exports = window.co.fn.append;
return exports;
});
Scalable and Modular Architecture for CSS and
JavaScript
Way to many thing like trigger on scroll on my page…
window.co = window.co || {};
window.co.Notification = {};
window.co.Notification.List = {};
window.co.Notification.events = {};
window.co.Notification.add = function (eventName, event, callBack) {
window.co.Notification.List[eventName] = {};
window.co.Notification.List[eventName].callBack = callBack;
window.co.Notification.List[eventName].event = event;
};
window.co.Notification.remove = function (eventName) {
delete window.co.Notification.List[eventName];
};
setInterval(function() {
var event;
for (event in window.co.Notification.List) {
if (window.co.Notification.List.hasOwnProperty(event)) {
if (window.co.Notification.events[window.co.Notification.List[event].event]) {
window.co.Notification.List[event].callBack();
}
}
}
for (event in window.co.Notification.events) {
if (window.co.Notification.events.hasOwnProperty(event)) {
window.co.Notification.events[event] = false;
}
}
}, 250);
JavaScript – Scroll
(function(window, jQuery) {
'use strict';
jQuery(window).scroll(function() {
window.co.Notification.events.Scroll = true;
});
}(window, jQuery));
JavaScript – Catching Errors
window.co.logjs = function (msg, url, line, level) {
if (Math.random() > 0.1) return; // only log some errors (many users will flood logs)
tmp=JSON.stringify(document.querySelectorAll("body").outerHTML)
var ajaxInput = '{ "strUrl" : "' + encodeURIComponent(url)
+ '", "strMsg" : "' + encodeURIComponent(msg)
+ '","strLine" : "' + encodeURIComponent(line)
+ '" ,"strLevel" : "' + encodeURIComponent(level)
+ '" }';
window.co.ajax("/core/jslog.asmx/Log", ajaxInput, function () {
}, function () {
});
};
window.onerror = function (msg, url, line) {
window.co.logjs(msg, url, line, 5);
return true;
};
JavaScript – One click function only
window.co = window.co || {};
window.co.hlr = function (element) {
var hlr;
if (!(hlr = element.getAttribute('x-hlr'))) {
return;
}
if (hlr == "PreventDefault") {
return;
}
var splitArray = element.getAttribute('x-hlr').split(' ');
for (var i = 0, items = splitArray.length; i < items; i++) {
hlr = splitArray[i];
if (window.co.fn[hlr]) {
window.co.fn[hlr](element);
} else {
curl(['/amd/’ + hlr + “/” + hlr], function (m) {
if(m != null)
m(element)
} else {
window.co.logjs("Core step undefined", hlr, 0, 4);
}
});
} } };
Descargar

Scalable and Modular Architecture CSS and JavaScript