Block Self-contained building unit of the interface

Block Fundamentals

Copy link to this section

block is fundamental to the entire methodology. This document explores the rationale behind treating everything on a page as a block, the benefits of this approach, and how it shapes the way we think about a page.

A block in Blocktail is a self-contained, reusable component that represents a distinct section or element of a web page. Blocks are the primary building units of our interface.

Block Characteristics

Copy link to this section
  • Self-contained: Blocks encapsulate their own styles and behavior.
  • Reusable: Blocks can be reused multiple times across a project.
  • Independent: Blocks function independently of their surroundings.
  • Modular: Blocks can be combined to create complex layouts.

Blocktail's Approach to Interface Component

Copy link to this section
  • block: Blocktail treats everything as a block, eliminating the need for redundant prefixes and reducing overall verbosity. This simplified syntax enhances code readability and maintainability.
  • context: Contexts provide a stable environment for blocks to adapt their appearance and behavior dynamically. This flexibility ensures blocks can respond to different scenarios without losing their core identity.
  • mutation: Mutations offer dynamic, block-specific changes, allowing for variations without modifying the block’s core structure. Denoted by double dashes (--), mutations add flexibility while preserving clarity.
  • tail: Tails, denoted by a single dash (-), structure internal elements of a block, offering clear hierarchy without unnecessary nesting.
  • ui--agent: For micro-level modifications, Blocktail uses ui-agent (prefixed with ui--), allowing for controlled utility-class-like styling while maintaining semantic clarity.

     

The "Everything is a Block" Philosophy

Copy link to this section

Blocktail encourages developers to think of every component on a page as a block. This approach offers several advantages:

By treating everything as a block, we create a consistent mental model for structuring our code. This consistency reduces cognitive load and makes it easier to understand and maintain large codebases.

Thinking in blocks naturally leads to more modular code. Each block becomes a discrete unit that can be developed, tested, and maintained independently.

Blocks are designed to be reusable. This approach encourages the creation of versatile components that can be used in multiple contexts, reducing code duplication.

As projects grow, the block-based approach scales well. New features can be added by creating new blocks or combining existing ones, without disrupting the overall structure.

The block structure provides clear boundaries between different parts of the interface, making it easier to reason about the codebase and debug issues.

Block Implementation

Copy link to this section

Block Naming Conventions

Copy link to this section

In Blocktail, we assume everything is a block by default. Therefore, no special prefix is required in class names. For example:

<article class="product_card">
  <!-- Product card content -->
</article>

Block Internal Structure

Copy link to this section

A block can contain other elements, which we call "tails" (we'll explore these in more depth later). Tails are denoted with a single dash (-):

<article class="product_card">
  <h2 class="-title">Product Name</h2>
  <p class="-description">Product description goes here.</p>
  <button class="-buy_button">Buy Now</button>
</article>

Block Superposition

Copy link to this section

Blocktail introduces the concept of superpositioned blocks, where a single block can exist in multiple states depending on its context. This allows blocks to adapt to different environments while maintaining their core structure and identity.

A block is defined once but can behave differently under different contexts.

<article class="product_card">
  <!-- This product card can adapt to different realities -->
</article>
<main class="context[featured_content]">
  <article class="product_card">
    <!-- The same product card, now in a featured reality -->
  </article>
</main>
<aside class="context[sidebar]">
  <article class="product_card">
    <!-- The same product card, now in a sidebar reality -->
  </article>
</aside>

This superposition concept allows for greater flexibility, enabling blocks to adapt seamlessly across different contexts while reducing code duplication.

Mutations allow for block-specific modifications that can be applied flexibly. They are denoted by double dashes (--), providing a clear way to create dynamic variants of a block.

<article class="product_card --featured --on_sale">
  <!-- A product card with featured and on-sale mutations -->
</article>

Mutation Advantages

  • Flexibility: Mutations enable state-dependent modifications that can be toggled dynamically or conditionally.
  • Clarity: The double-dash syntax clearly separates mutations from other class types, making it easy to differentiate block variants.
  • Modular Control: Applied at the block level, mutations maintain the modularity and reusability of the block.

While blocks are the primary units in Blocktail, they often contain smaller, related components. These are called "tails" and are denoted with a single dash (-). The term tail is chosen deliberately to avoid confusion with HTML elements and to provide a clear, concise way to describe these sub-components:

<nav class="main_navigation">
  <ul class="-menu">
    <li class="-item"><a class="-link" href="#">Home</a></li>
    <li class="-item"><a class="-link" href="#">About</a></li>
    <li class="-item"><a class="-link" href="#">Contact</a></li>
  </ul>
</nav>

Tail Advantages

  • Clarity: The single-dash prefix clearly identifies tails within a block.
  • Brevity: Tails use short, descriptive names, reducing verbosity in your HTML.
  • Scope: Tails are scoped to their parent block, preventing style conflicts.
  • Simplicity: The concept of tails is easy to grasp and apply consistently.

In CSS, tails are always defined under their parent block's class name, maintaining a clear hierarchy and scoping:

.main_navigation {
  /* Styles for the main navigation block */
  .-menu {
    /* Styles for the menu tail */
  }
  .-item {
    /* Styles for the item tail */
  }
  .-link {
    /* Styles for the link tail */
  }
}

This approach ensures that tail styles are properly scoped to their parent block, preventing unintended style conflicts and maintaining a clear relationship between blocks and their tails.

Tails provide a way to structure the internals of a block without creating unnecessary nesting or complexity. This approach keeps your HTML clean and semantic while providing clear relationships between blocks and their components.

The concept of blocks provides a powerful mental model for structuring web interfaces. By encouraging developers to think of everything as a block, we promote consistency, modularity, and maintainability in web development.

The introduction of superpositioned blocks and mutations offers a flexible and dynamic approach to component-based development. This innovative methodology allows for more adaptable and context-aware interfaces, while maintaining clarity and structure.

As you continue to work with Blocktail, you'll find that thinking in blocks becomes second nature, leading to cleaner, more organized, and more maintainable code. The concepts of superposition and mutation further enhance this approach, allowing you to create versatile components that can adapt to various contexts and states with minimal code duplication.