Skip to content

Instantly share code, notes, and snippets.

@dimitardanailov
Last active June 9, 2016 12:05
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save dimitardanailov/0425d9c4efa1dffb7b24193e8bc976b5 to your computer and use it in GitHub Desktop.
Save dimitardanailov/0425d9c4efa1dffb7b24193e8bc976b5 to your computer and use it in GitHub Desktop.
Front-end Lightning Talks: Object Oriented CSS Framework and Crazy Towns

Crazy Towns

It’s all about the key selector

What determines the impact of a selector is its key selector. The key selector is a very important thing in the world of CSS as browsers read selectors right to left. This means the key selector is the last one before the opening {, for example:

.header ul      { /* ‘ul’ is the key selector */ }
.ul li a        { /* ‘a’ is the key selector */ }
p:last-child    { /* ‘:last-child’ is the key selector */ }

Of course there are always exceptions. It’s perfectly reasonable to have selectors like .main-nav > li where your key selector is a type selector.

Resources:

When writing HTML you've probably noticed that it has a clear nested and visual hierarchy. CSS, on the other hand, doesn't.

nav {
  ul {
    margin: 0;
    padding: 0;
    list-style: none;
  }

  li { display: inline-block; }

  a {
    display: block;
    padding: 6px 12px;
    text-decoration: none;
  }
}
Resources:
nav {
  > ul {
    margin: 0;
    padding: 0;
    list-style: none;
  }

  > li { display: inline-block; }

  > a {
    display: block;
    padding: 6px 12px;
    text-decoration: none;
  }
}

Inheritance C# Programming Guide

// WorkItem implicitly inherits from the Object class.
public class WorkItem
{
    // Static field currentID stores the job ID of the last WorkItem that
    // has been created.
    private static int currentID;

    //Properties.
    protected int ID { get; set; }
    protected string Title { get; set; }
    protected string Description { get; set; }
    protected TimeSpan jobLength { get; set; }

    // Default constructor. If a derived class does not invoke a base-
    // class constructor explicitly, the default constructor is called
    // implicitly. 
    public WorkItem()
    {
        ID = 0;
        Title = "Default title";
        Description = "Default description.";
        jobLength = new TimeSpan();
    }

    // Instance constructor that has three parameters.
    public WorkItem(string title, string desc, TimeSpan joblen)
    {
        this.ID = GetNextID();
        this.Title = title;
        this.Description = desc;
        this.jobLength = joblen;
    }

    // Static constructor to initialize the static member, currentID. This
    // constructor is called one time, automatically, before any instance
    // of WorkItem or ChangeRequest is created, or currentID is referenced.
    static WorkItem()
    {
        currentID = 0;
    }


    protected int GetNextID()
    {
        // currentID is a static field. It is incremented each time a new
        // instance of WorkItem is created.
        return ++currentID;
    }

    // Method Update enables you to update the title and job length of an
    // existing WorkItem object.
    public void Update(string title, TimeSpan joblen)
    {
        this.Title = title;
        this.jobLength = joblen;
    }

    // Virtual method override of the ToString method that is inherited
    // from System.Object.
    public override string ToString()
    {
        return String.Format("{0} - {1}", this.ID, this.Title);
    }
}

// ChangeRequest derives from WorkItem and adds a property (originalItemID) 
// and two constructors.
public class ChangeRequest : WorkItem
{
    protected int originalItemID { get; set; }

    // Constructors. Because neither constructor calls a base-class 
    // constructor explicitly, the default constructor in the base class
    // is called implicitly. The base class must contain a default 
    // constructor.

    // Default constructor for the derived class.
    public ChangeRequest() { }

    // Instance constructor that has four parameters.
    public ChangeRequest(string title, string desc, TimeSpan jobLen,
                         int originalID)
    {
        // The following properties and the GetNexID method are inherited 
        // from WorkItem.
        this.ID = GetNextID();
        this.Title = title;
        this.Description = desc;
        this.jobLength = jobLen;

        // Property originalItemId is a member of ChangeRequest, but not 
        // of WorkItem.
        this.originalItemID = originalID;
    }
}

class Program
{
    static void Main()
    {
        // Create an instance of WorkItem by using the constructor in the 
        // base class that takes three arguments.
        WorkItem item = new WorkItem("Fix Bugs",
                                     "Fix all bugs in my code branch",
                                     new TimeSpan(3, 4, 0, 0));

        // Create an instance of ChangeRequest by using the constructor in
        // the derived class that takes four arguments.
        ChangeRequest change = new ChangeRequest("Change Base Class Design",
                                                 "Add members to the class",
                                                 new TimeSpan(4, 0, 0),
                                                 1);

        // Use the ToString method defined in WorkItem.
        Console.WriteLine(item.ToString());

        // Use the inherited Update method to change the title of the 
        // ChangeRequest object.
        change.Update("Change the Design of the Base Class",
            new TimeSpan(4, 0, 0));

        // ChangeRequest inherits WorkItem's override of ToString.
        Console.WriteLine(change.ToString());

        // Keep the console open in debug mode.
        Console.WriteLine("Press any key to exit.");
        Console.ReadKey();
    }
}
/* Output:
    1 - Fix Bugs
    2 - Change the Design of the Base Class
*/
Resources:
Velocity 2010: Nicole Sullivan, "The Top 5 Mistakes of Massive CSS":
05. Granularity fail - the css objects shouldn't match the PHP objects
04. Stale rules - CSS gets crufty
  • Truly stale - rules that are no longer used on the site.
  • Rules used on Subsequent PV or activated on user action

Udacity - Browser Rendering Optimization

03. Unpredictability - Make each object predictable and location indepent
02. Specifity UNPREDICTABILITY - Make each object predictable and location indepent
01. Duplication - CSS kudzu on steroids
html {
	margin: 0;
	padding: 0;
	height: 100%;
}

body {
	font-family: Corbel, Calibri, Arial;
	line-height: 15px;
	margin: 0;
	padding: 0;
	height: 100%;
	width: 100%;
	font-size: 62.5%;
	letter-spacing: normal;
	direction:ltr;
	overflow-x: hidden;
}

.main-wrapper {
	min-height: 100%;
	position: relative;
}

.main-section {
	position: relative;

	width: 100%;
	margin: 0 auto;
}

.footer-section {
	position: absolute;
	bottom: 0;
	width: 100%;
	/* Height of the footer */
	/* 
	height:60px; 
	 */			
}

.reset-item {
	padding: 0;
	margin: 0;
}

.flexible-image {
	width: 100%;
}

img {
	border: none;
}

/**** Floats ****/
.float-left,
.wrapper-grid-a > .wrapper-block-a,
.wrapper-grid-b > .wrapper-block-a, 
.wrapper-grid-b > .wrapper-block-b,
.wrapper-grid-b > .wrapper-block-c,
.wrapper-grid-c > .wrapper-block-a,
.wrapper-grid-f > .wrapper-block-a,
.wrapper-grid-f > .wrapper-block-b,
.wrapper-grid-f > .wrapper-block-c,
.wrapper-grid-f > .wrapper-block-d,
.wrapper-grid-f > .wrapper-block-e,
.wrapper-grid-g > .wrapper-block-a,
.wrapper-grid-g > .wrapper-block-b,
.wrapper-grid-g > .wrapper-block-c,
.wrapper-grid-g > .wrapper-block-d,
.wrapper-grid-e > .wrapper-block-a,
.wrapper-grid-j > .wrapper-block-a,
.wrapper-grid-h > .wrapper-block-a,
.wrapper-grid-i > .wrapper-block-a,
.wrapper-grid-k > .wrapper-block-a,
.wrapper-grid-k > .wrapper-block-b,
.wrapper-grid-l > .wrapper-block-a {
	float: left;
}

.float-right,
.wrapper-grid-a > .wrapper-block-b,
.wrapper-grid-c > .wrapper-block-b,
.wrapper-grid-e > .wrapper-block-b,
.wrapper-grid-j > .wrapper-block-b,
.wrapper-grid-h > .wrapper-block-b,
.wrapper-grid-k > .wrapper-block-c {
	float: right;
}

.clear {
	clear: both;
}

.container-clear-floats:after,
.wrapper-grid-a:after,
.wrapper-grid-b:after,
.wrapper-grid-c:after,
.wrapper-grid-e:after,
.wrapper-grid-f:after,
.wrapper-grid-g:after,
.wrapper-grid-j:after,
.wrapper-grid-h:after,
.wrapper-grid-i:after,
.wrapper-grid-k:after,
.wrapper-grid-l:after,
.list-float-left:after {
	content: '';
	display: block;
	clear: both;
	height: 0;
}

/*** Clear - IE Fix ***/
.container-clear-floats,
.wrapper-grid-a,
.wrapper-grid-b,
.wrapper-grid-c,
.wrapper-grid-e,
.wrapper-grid-f,
.wrapper-grid-g,
.wrapper-grid-j,
.wrapper-grid-h,
.wrapper-grid-i,
.wrapper-grid-k,
.wrapper-grid-l,
.list-float-left {
	display: inline-block;
	display: block;
	zoom:1;
}
/*** Clear - IE Fix ***/
/**** END Floats ****/

/**** Display *******/
.display-none {
	display: none;
}

.display-block {
	display: block;
}

.display-inline {
	display: inline;
}

.display-inline-block {
	display: inline-block;
}
/**** END Display *****/

/**** Opacity *****/
.opacity-zero {
	opacity: 0;

	-ms-filter: "alpha(opacity=0)";
	filter: alpha(opacity=0);
}

.opacity-full-visible {
	opacity: 1;

	-ms-filter: "alpha(opacity=100)";
	filter: alpha(opacity=100);
}
/**** END Opacity *****/

.hidden {
	position: absolute !important;
	top: -9999px !important;
	left: -9999px !important;
}

.position-absolute {
	position: absolute;
}

.position-fixed {
	position: fixed;
}

.position-relative {
	position: relative;
}

.posision-right {
	right: 0;
}

/********************* Text *********************/
.text-align-left {
	text-align: left;
}

.text-align-center,
.box-text {
	text-align: center;
}

.text-align-right {
	text-align: right;
}

.text-decoration-none {
	text-decoration: none;
}

.underline {
	text-decoration: underline;
}

.justify {
	text-align: justify;
}

.font-weight-normal {
	font-weight: normal;
}

.bold {
	font-weight: bold;
}

.italic {
	font-style: italic;
}

.lowercase {
	text-transform: lowercase;
}

.uppercase {
	text-transform: uppercase;
}

.capitalize {
	text-transform: capitalize;
}

.hover-underline:hover {
	text-decoration: underline;
}

.text-overflow {
	overflow: hidden;
	white-space: nowrap;    
}

.text-ellipsis,
.text-overflow {
	-webkit-text-overflow: ellipsis;
	 -khtml-text-overflow: ellipsis;
		-icab-text-overflow: ellipsis;
		 -moz-text-overflow: ellipsis;
			 -o-text-overflow: ellipsis;
					text-overflow: ellipsis;
}

.outline-none {
	outline: none;
}


.color-inherit {
	color: inherit;
}

.text-link {
	text-decoration: none;
}

.text-link:hover {
	text-decoration: underline;
}
/********************* Text *********************/

.overflow-hidden {
	overflow: hidden
}

.white-space-nowrap {
	white-space: nowrap;
}

/********************* Width *********************/
.fill-parent {
	width: 100%;
}

/***************** Layouts Dimensions **********/

/*********** grid-a Start ***********/
.wrapper-grid-a > .wrapper-block-a, 
.wrapper-grid-a > .wrapper-block-b {
	width: 50%;
}
/*********** grid-a END *************/

/*********** grid-b Start ***********/
.wrapper-grid-b > .wrapper-block-a, 
.wrapper-grid-b > .wrapper-block-c {
	width: 25%;
}

.wrapper-grid-b > .wrapper-block-b {
	width: 40%;
	margin: 0% 5%;
}
/*********** grid-b END *************/

/*********** grid-c Start ***********/
.wrapper-grid-c > .wrapper-block-a,
.wrapper-grid-c > .wrapper-block-b {   
	width: 45%;
}
/*********** grid-c END *************/


/*********** grid-e Start ***********/
.wrapper-grid-e > .wrapper-block-a {
	width: 65%;
	margin-right: 5%;
}

.wrapper-grid-e > .wrapper-block-b {
	width: 30%;
}
/*********** grid-e END *************/

/*********** grid-f Start ***********/
.wrapper-grid-f > .wrapper-block-a,
.wrapper-grid-f > .wrapper-block-b,
.wrapper-grid-f > .wrapper-block-c,
.wrapper-grid-f > .wrapper-block-d,
.wrapper-grid-f > .wrapper-block-e {
	width: 20%;
}
/*********** grid-f END *************/

/*********** grid-g Start ***********/
.wrapper-grid-g > .wrapper-block-a,
.wrapper-grid-g > .wrapper-block-b,
.wrapper-grid-g > .wrapper-block-c,
.wrapper-grid-g > .wrapper-block-d {
	width: 25%;
}
/*********** grid-g END *************/

/*********** grid-j Start ***********/
.wrapper-grid-j > .wrapper-block-a {
	width: 25%;
}

.wrapper-grid-j > .wrapper-block-b {
	width: 74%;
}
/*********** grid-j END *************/

/*********** grid-h ***********/
.wrapper-grid-h > .wrapper-block-a {
	width: 25%;
}

.wrapper-grid-h > .wrapper-block-b {
	width: 65%;
}
/*********** grid-h END *************/

/*********** grid-i Start ***********/
.wrapper-grid-i > .wrapper-block-a  {
	width: 14.25%;
}
/*********** grid-i END *************/

/*********** grid-k Start ***********/
.wrapper-grid-k > .wrapper-block-a,
.wrapper-grid-k > .wrapper-block-c {
	width: 31.33%;
}

.wrapper-grid-k > .wrapper-block-b {
	width: 31.33%;
	margin: 0 3%;
}
/*********** grid-k END *************/

/*********** grid-l Start ***********/
.wrapper-grid-l > .wrapper-block-a {
	width: 16.6%;
}
/*********** grid-l END *************/

/***************** END Layouts Dimensions *********/

/********************* Width *********************/

/******************** Cursors ********************/
/*** https://css-tricks.com/almanac/properties/c/cursor/ ***/
.auto            { cursor: auto; }
.default         { cursor: default; }
.none            { cursor: none; }
.context-menu    { cursor: context-menu; }
.help            { cursor: help; }
.pointer         { cursor: pointer; }
.progress        { cursor: progress; }
.wait            { cursor: wait; }
.cell            { cursor: cell; }
.crosshair       { cursor: crosshair; }
.text            { cursor: text; }
.vertical-text   { cursor: vertical-text; }
.alias           { cursor: alias; }
.copy            { cursor: copy; }
.move            { cursor: move; }
.no-drop         { cursor: no-drop; }
.not-allowed     { cursor: not-allowed; }
.all-scroll      { cursor: all-scroll; }
.col-resize      { cursor: col-resize; }
.row-resize      { cursor: row-resize; }
.n-resize        { cursor: n-resize; }
.e-resize        { cursor: e-resize; }
.s-resize        { cursor: s-resize; }
.w-resize        { cursor: w-resize; }
.ns-resize       { cursor: ns-resize; }
.ew-resize       { cursor: ew-resize; }
.ne-resize       { cursor: ne-resize; }
.nw-resize       { cursor: nw-resize; }
.se-resize       { cursor: se-resize; }
.sw-resize       { cursor: sw-resize; }
.nesw-resize     { cursor: nesw-resize; }
.nwse-resize     { cursor: nwse-resize; }
/******************** Cursors ********************/

/********************* Outline *********************/
textarea,
select,
input[type="email"],
input[type="number"],
input[type="password"],
input[type="text"],
input[type="url"] {
	outline: none;
}

/********************* List *********************/
.reset-list {
	margin: 0;
	padding: 0;
	list-style: none;
}

.list-inline > li {
	display: inline;
}

.list-float-left > li {
	float: left;
}

.list-style-lower-alpha {
	list-style: lower-alpha;
}

.list-style-upper-alpha {
	list-style: upper-alpha;
}

/******** Fix for numeric list *****/
.numberic-list-wrapper {
	counter-reset:section;
}

.numberic-list-main {
	counter-reset:subsection;
	counter-reset: childsubsection;
	list-style: none;
}

.numberic-list-main > li:before {
	counter-increment:section;
	content:counter(section) ". ";
}

.numberic-list-main-sublist {
	counter-reset: childsubsection;
	list-style: none;
}

.numberic-list-main-sublist > li:before {
	counter-increment:subsection;
	content:counter(section) "." counter(subsection) ". ";
}

.numberic-list-main-sublist-child {
	list-style: none;
}

.numberic-list-main-sublist-child > li:before {
	counter-increment: childsubsection;
	content: counter(section) "." counter(subsection) "." counter(childsubsection) ". ";
}

.numberic-list-sublist-reset-item:before {
	counter-reset:subsection;
}
/******** Fix for numeric list *****/

/********************* Table *********************/
.border-collapse {
	border-collapse: collapse;
}

/********************* Triangle *********************/
.arrow
{
	width: 0;
	height: 0;
}

.middle-arrow
{
	margin: 0 auto;
}
/********************* Triangle *********************/

/********************* Form Elements ***************/
.input-text-field {
	width: 98%;
}

.input-inline {
	display: inline-block;
	width: 60%;
}

/************** Select ***********/
.select-box > select {
	cursor: pointer;

	-webkit-appearance: button;
	-moz-appearance: button;

	width: 100%;
	min-height: 100%;
	max-width: 100%;

	z-index: 2;
	position: absolute;

	opacity: 0;
	-ms-filter: "alpha(opacity=0)";
	filter: alpha(opacity=0);

	left: 0;
	top: 0;
}
/************** Select ***********/
/** base.css **/
.icons {
	position: relative;

	display: block;

	background-color: transparent;
	background-repeat: no-repeat;

	cursor: pointer;
}
/** icons.css **/
.small-icons {
	height: 18px;
	width: 20px;

	background-image: url("/icons/small-icons/20x18.png");
}

.small-icon-add-to-basket {
	background-position: 0 -18px;
}

.small-icon-plus-sign {
	background-position: 0 -36px;
}

.small-icon-minus-sign {
	background-position: 0 -54px;
}
<span class="icons small-icons small-icon-add-to-basket"></span>
<span class="icons small-icons small-icon-plus-sign"></span>
<span class="icons small-icons small-icon-minus-sign"></span>

Angular 2

@Component({
  'selector': 'story-characters', // selector is the name of the element in the Template
  'templateUrl': './app/characters.component.html', // templateUrl point to the template  
  'styleUrls': ['./app.characters.component.css'], // styleUrls point to the styles
  'directives': [CharacterDetailComponent], // directives declare custom directives it uses
  'providers': [HTTP_PROVIDERS, CharacterService] // providers declare services the Component needs
})

export class CharactersComponent implements OnInit {
  // Component can communite to anyone hosting it.
  @Output() changed = new EventEmitter<Character>();
  
  // Pass values into the nested component
  @Input() storyId: number;
  
  characters: Character[];
  selectedCharacter: Character;
  
  constructor(private _characterService: CharacterService) { }
  
  ngOnInit() {
    this._characterService.getCharacters(this.storyId)
      .subscribe(characters => this.characters = characters);
  }
  
  select(selectedCharacter: Character) {
    this.selectedCharacter = selectedCharacter;
    
    // Component emits events via output
    this.changed.emit(selectedCharacter);
  }
}

Demo

Resources:

React

class MyNotification extends React.CSSComponent {
  render() {
    var styleMap = this.mountStyles`
      @media (min-width: 600px) {
        .notification {
          padding: 15px;
        }
      }
      .notification {
        border: 10px solid ${this.props.color};
        padding: 10px;
        color: #333;
      }
      /* ".notification span" is rejected by ModularCSS as it
       * contains a nested CSS selectors. Therefore, need to
       * use a new class name instead. */  
      .notification-hint {
        font-style: italic;
      }`;
    return (
      <div className={styleMap.notification}>
        {this.props.prompt}
        <span className={styleMap.notificationHint}>
          {this.props.hint}
        </span>
      </div>);
  }
}
Resources:
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment