Navigation Menu

Skip to content

Instantly share code, notes, and snippets.

@adamjgrant
Last active March 22, 2016 16:19
Show Gist options
  • Star 6 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save adamjgrant/599530dab67db17c5b2d to your computer and use it in GitHub Desktop.
Save adamjgrant/599530dab67db17c5b2d to your computer and use it in GitHub Desktop.
Scoped components is a pattern to group css classes and ids into "Components" which identify high-level units of visual organization in the application.

Scoped components

CSS class names quickly get out of hand. Repos end up with unorganized CSS files all over the place making it difficult to name things and find them in the code.

The scoped components pattern addresses this by grouping classes into "component" scopes.

<div data-component="news-menu">
  <h1 class="title">...</h1>
  <ul class="items">
    <li class="item">...</li>
    ...
  </ul>
  <aside id="breaking"></aside>
</div>

Now, when you want to write some code around the "News" box on your page, you can write everything in the context of the news component.

Instead of

$('#news-menu_breaking').click(function() {
  $('.news-menu_get').html("Loading breaking news...");
});
  
$('.news-menu_item').click(function() {
  $('#news-menu_loading-spinner').show();
  location.href = $(this).data('url');
});

Define a scope

$.component('news-menu', function($scope) {
  $scope('#breaking').click(function() {
    $scope('.get').html("Loading breaking news...");
  });
  
  $scope('.item').click(function() {
    $scope('#loading-spinner').show();
    location.href = $scope(this).data('url');
  });
});

See an example using jQuery or use the plugin

This also lets us keep css class names ultra simple. Instead of .news_menu-breaking or .news_menu-title, just use .breaking or .title keeping your code very readable without fear of it running into other classes.

[data-component="news-menu"] .title {
  font-size: 18px;
  font-family: helvetica, sans-serif;
}

Also see Amadeus

<!DOCTYPE HTML>
<!-- Use data-component to denote elements as scoped components -->
<html>
<head>
<link rel="stylesheet" href="news-menu.css">
</head>
<body>
<div data-component="news-menu">
<h1 class="title">News</h1>
<ul class="items">
<li class="item">War Breaks out in Middle East.</li>
<li class="item">New Bill Passed into Law.</li>
</ul>
<aside id="breaking"></aside>
</div>
<script src="news-menu.js"></script>
</body>
</html>
/* Simply scope classes under the component
to keep class names simple and separate. */
[data-component="news-menu"] {
padding: 25px;
border-radius: 10px;
border: 1px solid #CCC;
}
[data-component="news-menu"] .title {
font-size: 18px;
font-family: helvetica, sans-serif;
}
[data-component="news-menu"] .items {
list-style: none;
padding-left: 0;
}
[data-component="news-menu"] .items .item {
line-height: 20px;
}
// Functions can be created to scope event listeners
// to components allowing us to use simple names for
// component ids and organize JS code into component-
// specific files.
component('news-menu', function(scope) {
scope.click('#breaking', function() {
scope(this).innerHTML = "Loading breaking news...";
});
scope.click('.item', function(scope) {
$('#loading-spinner').show();
location.href = scope.dataset.url;
});
});
/* Simply scope classes under the component
to keep class names simple and separate. */
@include component('news-menu') {
padding: 25px;
border-radius: 10px;
border: 1px solid #CCC;
.title {
font-size: 18px;
font-family: helvetica, sans-serif;
}
.items {
list-style: none;
padding-left: 0;
.item {
line-height: 20px;
}
}
}
// HTML Preprocessor mixins can make this easy for us.
// See: https://gist.github.com/emilebosch/9e5c25833b8f92dfd4db
component "news-menu" do
.title News
ul.items
li.item War Breaks out in the Middle East.
li.item New Bill Passed into Law
#breaking

Keep your code tidy

An actual example of using this pattern from YesNo

Isn't it nice to keep things organized?

Implementation in JS

Implementation in JS

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment