Successfully reported this slideshow.

The Thinking behind BEM

909 views

Published on

Published in: Technology, Education
  • Be the first to comment

The Thinking behind BEM

  1. 1. ({ name: "Varvara Stepanova", email: "toivonen@yandex-team.ru", twitter: "@toivonens" }); 2
  2. 2. Search Images Video Realty Blogs Apps Jobs • Russia • Turkey • Ukraine • Belarus Maps • Kazakhstan • Azerbaijan 3 Social • 2000 devs • 150+ frontenders • 100+ services Mail Marketplace etc.
  3. 3. The thinking behind BEM #b_ #askbem @bem_en UI Framework Team Leader Varvara Stepanova
  4. 4. Block • Element • Modifier 5
  5. 5. Page of independent blocks 6
  6. 6. Page of independent blocks page.html <body class="page"> <div class="header"> <img class="logo" ... /> <div class="search">...</div> <div class="menu">...</div> </div> <div class="layout"> <div class="sidebar">...</div> <div class="menu">...</div> </div> </body> 7
  7. 7. Block with elements 8
  8. 8. Block with elements page.html <div class="tabbed-pane"> <ul> <li class="tabbed-pane__tab">Tab1</li> <li class="tabbed-pane__tab">Tab2</li> </ul> <div class="tabbed-pane__panel"> ... </div> </div> 9
  9. 9. Modifiers change blocks and elements <div class=" tabbed-pane tabbed-pane_theme_blue"> ... </div> <div class=" tabbed-pane tabbed-pane_to_bottom"> ... </div> 10
  10. 10. http://bem.info 11
  11. 11. Thinking of... 1. Development semantics 2. Doing magic 3. Design philosophy
  12. 12. Development semantics
  13. 13. Block, element, modifier 14
  14. 14. CSS pseudoCSS .t-pane { width: 200px; &_theme { &_blue { background: #9cf; } } &__tab { display: inline-block; } 15 .t-pane { width: 200px; } .t-pane_theme_blue { background: #9cf; } .t-pane__tab { display: inline-block; }
  15. 15. Take a block, take its element, do this! JavaScript $block('tabbed-pane') .elem('tab') .click(...); $block('tabbed-pane') .setMod('view', 'flipped'); $block('tabbed-pane') .elem('tab') .setMod('current'); 16
  16. 16. Multiple technologies tabbed-pane/ tabbed-pane.css tabbed-pane.js tabbed-pane.bemhtml tabbed-pane.md logo/ logo.png logo.css logo.bemhtml logo.md 17 search/ search__autocomplete.css search__autocomplete.js search__autocomplete.md search.css search.js search.bemhtml search.md
  17. 17. Blocks are consistent components ... <div class="tabbed-pane"> ... </div> ... • internal structure • associated view • corresponding behavior 18
  18. 18. Doing magic
  19. 19. Doing magic Robots and people Who serves whom?!
  20. 20. Заголовок (не длинней одной строки) Do we like what robots like?
  21. 21. Tidy CSS code • YUI Compressor • clean-css • Microsoft • SASS • CSS Tidy • Slimmer • Stilys • whatever 22 :link:hover,:visited:hover{color:#f00!important}:link{ wbr{display:inline-block}body{font:.8em Arial,Helve serif;position:relative;z-index:0;margin:0;padding:0 0;color:#000;background:#fff}*{font-size:100%;marg weight:normal;padding:0}table{border-collapse:coll align:left;vertical-align:top;border-collapse:collapse ol,ul,li{padding:0}code,input,textarea{font-family:Ar a{text-decoration:none}:link,:visited{text-decoration img,fieldset{border:0}b{font-weight:normal}i{font-s size:100%;width:100%;border-collapse:collapse}.hea gc,.head-c,.head-gr,.head-r{padding:0;vertical-align 2%}.head-gap{display:block;visibility:hidden;width:2 gap{width:3.1em}.head-l{width:12%;padding-top:1e gl{width:4%}.head-c{width:60%}.head-gr{width: 4%}:link{color:#1a3dc1}:link:hover,:visited:hover{colo
  22. 22. CSS best practices /* Use shorthand */ #super-box { margin-top: 9px; margin-right: 8px; margin-bottom: 0; margin-left: 5px; margin: 9px 8px 0 5px; } /* Numeric font-weight */ p.about { font-weight: bold; font-weight: 700; } 23 /* Shorter color code */ li.menu { color: yellow; color: #FF0; background-color: #F00; background-color: red; } /* Combine selectors */ h1, h2, h3 { text-decoration: none; }
  23. 23. bem.info/tools/csso BEFORE .test1 { border: none; background-color: red; margin-top: 2em; margin-left: 4px; margin-bottom:3px; margin-right: 0.1em; font-weight: bold; } AFTER .test1 { background-color: red; margin: 2em .1em 3px 4px; font-weight: 700 } .test2 { border: none; } .test3 { margin-top: 2em; margin-bottom: 2em; margin-right: 2em; margin-left: 2em; background-color: #FF0000; font-weight: normal; } 24 .test1, .test2 { border: none } .test3 { margin: 2em; background-color: red; font-weight: 400 }
  24. 24. Modular or solid? 25
  25. 25. human @import url(blocks/header.css); @import url(blocks/layout.css); @import url(blocks/menu.css); @import url(blocks/search.css); @import url(blocks/button.css); @import url(blocks/text.css); @import url(blocks/footer.css); blocks/ button.css footer.css header.css layout.css menu.css search.css 26 browser .header { background: #000; color: #fff; font-size: 1.5em; } .layout { ... } .menu { ... } .search__input { width: 100%; margin: 0; -webkit-box-sizing: border-box; -moz-box-sizing: border-box; box-sizing: border-box; } .search_button { margin: 0; }
  26. 26. CSS flattening with Borschik index.css @import url(blocks/header/header.css); @import url(blocks/menu/menu.css); ... _index.css .header { ... } .menu { ... } 27
  27. 27. CSS flattening with Borschik blocks/my-block/my-block.css .my-block { background: url(bg.png); } pages/_index.css /* Included blocks/my-block/my-block.css */ .my-block background: url(../blocks/my-block/bg.png); } ... 28
  28. 28. JavaScript flattening with Borschik index.js /*borschik:include:blocks/menu/menu.js*/ /*borschik:include:blocks/tabbed-pane/tabbed-pane.js*/ ... _index.js /* Included blocks/menu/menu.js */ (function($) { $block('menu').elem('item').on('click', function() { $(this).toggleMod('state', 'current'); }); })(jQuery); 29
  29. 29. Borschik freezes images blocks/my-block/my-block.css .my-block { background: url(bg.png); } pages/_index.css /* Included blocks/my-block/my-block.css */ .my-block { background: url(_freeze/jUK5O9GsS2gPWOhRMeBxR0GThf0.png); } ... 30
  30. 30. bit.ly/about-borschik Borschik. Simply powerful :-) 31
  31. 31. Code interfaces, not languages general CSS HTML .head { ... } .menu { ... } <!DOCTYPE html> .menu__item { ... } <html> .phone { ... } <head> .layout <title>Awesome online bookshop</title> { ... } ... <link rel="stylesheet" href="style.css"/> <script src="magic.js"></script> </head> CSS for IE <body> <div class="head"> .menu { ... } <ul class="menu"> .menu__item { ... } <li class="menu__item"><a href="/">Home</a></li> .button { ... } <li class="menu__item"><a href="/news">News</a></li> ... ... JavaScript </ul> <div class="phone">+3 71 1234567</div> (function($) { </div> $block('menu').elem('item').on('click', function() { <div class="layout"> $(this).toggleMod('state', 'current'); ... }); })(jQuery); ... 32
  32. 32. Code interfaces, not languages BEM tree { block: 'page', content: [ { block: 'head', content: [ { block: 'logo' }, { block: 'search', ... }, { block: 'menu' } ] } 33
  33. 33. Supply a browser with magic outcome page.html <!DOCTYPE html><html class="i-ua_js_no iua_css_standart"><head><meta charset=UTF-8"><meta httppage.css equiv="X-UA-Compatible" content="IE=EmulateIE7, IE=edge"><script type="text/javascript">//<!-:link:hover,:visited:hover{color:#f00!important}:link{color:#1a3dc1} ;(function(d,e,c,r) wbr{display:inline-block}body{font:.8em Arial,Helvetica,sans{e=d.documentElement;c="className";r="replace";e[c]=e[c][r]("ipage.js serif;position:relative;z-index:0;margin:0;padding:0 0 1em ua_js_no","i-ua_js_yes");if(d.compatMode! 0;color:#000;background:#fff}*{font-size:100%;margin:0} jQuery.cookie=function(b,j,m){if(typeof j!="undefined"){m=m|| ="CSS1Compat")e[c]=e[c][r]("i-ua_css_standart","ih1,h2,h3,h4,h5,h6{font-weight:normal;padding:0}table{border{};if(j===null){j="";m.expires=-1}var e="";if(m.expires&&(typeof ua_css_quirks")}(document)); collapse:collapse}th,td{padding:0;text-align:left;verticalm.expires=="number"||m.expires.toUTCString)){var f;if(typeof //--></script><!--[if gt IE 9]><!--><link rel="stylesheet" align:top;border-collapse:collapse}ol,ul{list-style:none} m.expires=="number"){f=new Date();f.setTime(f.getTime()+ ol,ul,li{padding:0}code,input,textarea{font(m.expires*24*60*60*1000))}else{f=m.expires}e="; family:Arial,Helvetica,sans-serif}a{textexpires="+f.toUTCString()}var l=m.path?"; path="+(m.path):"";var decoration:none}:link,:visited{text-decoration:underline}a g=m.domain?"; domain="+(m.domain):"";var a=m.secure?"; secure":"";document.cookie=[b,"=",encodeURIComponent(j),e,l,g,a].j oin("")}else{var d=null;if(document.cookie&&document.cookie!="") {var k=document.cookie.split(";");for(var h=0;h<k.length;h++){var 34
  34. 34. Introducing magic into development developer 35 building process browser
  35. 35. Building process › bem make › bem server Production Development • rebuild the whole project 36 • live edit • partial rebuild • tracking changes
  36. 36. bem.info/tools 37
  37. 37. Design philosophy
  38. 38. 39
  39. 39. 40
  40. 40. Independent CSS blocks bit.ly/bem-riga-2012 What you can borrow from Yandex front-end dev • blocks – are not affected by parents – do not affect children • developer – names blocks with CSS classes – keeps off tag selectors – avoids cascade 41
  41. 41. Imperative vs declarative programming COULD YOU PLEASE ? 42
  42. 42. Declarations in CSS file1.css .button { background-color: red; font-size: 1.5em; } file2.css .button { background-color: green; margin: .2em; } 43
  43. 43. Declarative JavaScript file1.js BEM.DOM.decl('button', { /* Basic block implementation */ }); file2.js BEM.DOM.decl('button', { /* Extending block implementation */ }); 44
  44. 44. Declarative JavaScript BEM.DOM.decl('button', { onSetMode: { 'active' : { 'yes' : function() { /* Do smth when active */ }, 'no' : function() { /* Do smth else when not */ } } } }); 45 <input class="button button_active_no" ... /> button_active_yes"
  45. 45. Combinatorics 46
  46. 46. simple & simple = complex 47
  47. 47. Extended by a modifier button.css .button { background-color: red; font-size: 1.5em; } button_size_large.css .button_size_large { font-size: 3em; } <input class="button button_size_large" ... /> 48
  48. 48. Extended by a modifier button.js BEM.DOM.decl('button', { /* Basic implementation for all the buttons */ }); button_size_large.js BEM.DOM.decl({ block: 'button', mod: 'size', val: 'large'}, { /* Additional implementation for large sized buttons */ }); <input class="button button_size_large" ... /> 49
  49. 49. Extended by a block level library-blocks/button/button.css library-blocks/ .button { background-color: red; font-size: 1.5em; button/ button.css button.js } menu/ search/ tabbed-pane/ blocks/button/button.css .button { blocks/ button/ button.css background-color: green; padding: .2em; } 50
  50. 50. Extended by a block level library-blocks/button/button.js library-blocks/ BEM.DOM.decl('button', { button/ button.css button.js /* Basic implementation for all the buttons*/ }); menu/ search/ tabbed-pane/ blocks/ button/ button.js blocks/button/button.js BEM.DOM.decl('button', { /* Additional implementation for the buttons of the project */ }); 51
  51. 51. Large profit of small things • larger entities made up from smaller ones – code re-use – consistency • everything is a block 52
  52. 52. Revelations • Development semantics • Magic building tricks • Declarativeness • Combinatory methods • Block levels and libraries 53
  53. 53. code more to code less 54
  54. 54. Varvara Stepanova UI Framework Team Lead toivonen@yandex-team.ru @toivonens Thank you
  55. 55. #b_ #askbem @bem_en 56 ?

×