Twig-blocks are native to the Twig-language. Twig’s documentation defines them as: 
“Blocks are used for inheritance and act as placeholders and replacements at the same time.”

Overwriting content #

Let’s have a look at how node.html.twig looks like from core. (simplified for readability sake)

node
Twig Created with Sketch.
node.html.twig
{%
  set classes = [
    'node',
    'node--type-' ~ node.bundle|clean_class,
  ]
%}

<article{{ attributes.addClass(classes) }}>
  <div{{ content_attributes }}>
    {{ content }}
  </div>
</article>

Say, we want to add a label "blieblabloo" and position it above the{{ content }}. We want this change for all the full view modes of nodes.

Then that means that we first create a node--full.html.twig that extends from the node.html.twig:

node
Twig Created with Sketch.
node.html.twig
{%
  set classes = [
    'node',
    'node--type-' ~ node.bundle|clean_class,
  ]
%}

<article{{ attributes.addClass(classes) }}>
  <div{{ content_attributes }}>
    {{ content }}
  </div>
</article>
Twig Created with Sketch.
node--full.html.twig
{% extends 'node.html.twig' %}

Secondly, we investigate what part of the base-template we want to overwrite, in this case it is the {{ content }} part. So inside the node.html.twig, we wrap the part that we want to to overwrite in a block tag. 

We should name block tags to the variables they hold, in this case we are using the name “content”.

Our example now looks as follows:

node
Twig Created with Sketch.
node.html.twig
{%
  set classes = [
    'node',
    'node--type-' ~ node.bundle|clean_class,
  ]
%}

<article{{ attributes.addClass(classes) }}>
  <div{{ content_attributes }}>
    {% block content %}
      {{ content }}
    {% endblock %}
  </div>
</article>
Twig Created with Sketch.
node--full.html.twig
{% extends 'node.html.twig' %}

{% block content %}
  <span>blieblabloo</span>
  {{ content }}
{% endblock %}

And that’s it! You are now overwriting the parts of the original template that you want to overwrite. And you keep all the rest intact.

The placeholder-principle #

Creating new Twig block tags has no impact on the original template. When Drupal encounters a block tag in a template that is not extending, it will do the nothing different as if that block tag wasn’t there. Drupal will render the markup inside the tag, because it functions as a placeholder until it's overwritten.

The replacement-principle #

When you are working inside a template that uses {% extends %}, you can only influence the base template by using block tags. Each line you write inside a template that extends, should be wrapped in blocks.

Overwriting attributes #

Overwriting attributes is quite advanced, and there is a good chance you will have no need for it. But in case you do, let's use the same above example.

If we want to add a class to the attributes of node--full.html.twig, we should also use Twig blocks. We can do that by using a Twig block in node.html.twig that is defined before the attributes are printed.

node
Twig Created with Sketch.
node.html.twig
{%
  set classes = [
    'node',
    'node--type-' ~ node.bundle|clean_class,
  ]
%}

{% block before %}{% endblock %}
<article{{ attributes.addClass(classes) }}>
  <div{{ content_attributes }}>
    {% block content %}
      {{ content }}
    {% endblock %}
  </div>
</article>
Twig Created with Sketch.
node--full.html.twig
{% extends 'node.html.twig' %}

{% block before %}
  {{ attach_library(‘my-theme/node--full') }}
  {% set attributes = attributes.addClass('my-shiny-class') %}
{% endblock %}

The above would result in only node--full items having the my-shiny-class.