diff --git a/src/Plugin/DisplayVariant/BlockDisplayVariant.php b/src/Plugin/DisplayVariant/BlockDisplayVariant.php
index 7e5e394..a5d2e21 100644
--- a/src/Plugin/DisplayVariant/BlockDisplayVariant.php
+++ b/src/Plugin/DisplayVariant/BlockDisplayVariant.php
@@ -13,11 +13,13 @@
 use Drupal\Component\Utility\SafeMarkup;
 use Drupal\Component\Uuid\UuidInterface;
 use Drupal\Core\Cache\Cache;
+use Drupal\Core\Cache\CacheableMetadata;
 use Drupal\Core\Display\VariantBase;
 use Drupal\Core\Form\FormStateInterface;
 use Drupal\Core\Plugin\ContainerFactoryPluginInterface;
 use Drupal\Core\Plugin\ContextAwarePluginInterface;
 use Drupal\Core\Plugin\Context\ContextHandlerInterface;
+use Drupal\Core\Render\Element;
 use Drupal\Core\Session\AccountInterface;
 use Drupal\Core\Url;
 use Drupal\Core\Utility\Token;
@@ -230,7 +232,7 @@ public function buildBlock($build) {
     $content = $build['#block_plugin']->build();
     // Remove the block plugin from the render array.
     unset($build['#block_plugin']);
-    if (!empty($content)) {
+    if ($content !== NULL && !Element::isEmpty($content)) {
       $build['content'] = $content;
     }
     else {
@@ -243,6 +245,15 @@ public function buildBlock($build) {
         '#cache' => $build['#cache'],
       ];
     }
+    // If $content is not empty, then it contains cacheability metadata, and
+    // we must merge it with the existing cacheability metadata. This allows
+    // blocks to be empty, yet still bubble cacheability metadata, to indicate
+    // why they are empty.
+    if (!empty($content)) {
+      CacheableMetadata::createFromRenderArray($build)
+        ->merge(CacheableMetadata::createFromRenderArray($content))
+        ->applyTo($build);
+    }
     return $build;
   }
 
diff --git a/tests/src/Unit/BlockDisplayVariantTest.php b/tests/src/Unit/BlockDisplayVariantTest.php
index 20776b5..2c576dc 100644
--- a/tests/src/Unit/BlockDisplayVariantTest.php
+++ b/tests/src/Unit/BlockDisplayVariantTest.php
@@ -10,6 +10,7 @@
 use Drupal\Component\Uuid\UuidInterface;
 use Drupal\Core\Block\BlockPluginInterface;
 use Drupal\Core\Cache\Cache;
+use Drupal\Core\Cache\CacheableMetadata;
 use Drupal\Core\Cache\Context\CacheContextsManager;
 use Drupal\Core\Plugin\Context\ContextHandlerInterface;
 use Drupal\Core\Plugin\ContextAwarePluginInterface;
@@ -176,6 +177,96 @@ public function testBuildNoCache() {
     $this->assertSame($expected_build, $build);
   }
 
+  /**
+   * Tests the build() method when a block is empty.
+   *
+   * @covers ::build
+   */
+  public function testBuildEmptyBlock() {
+    $container = new ContainerBuilder();
+    $cache_contexts = $this->prophesize(CacheContextsManager::class);
+    $container->set('cache_contexts_manager', $cache_contexts->reveal());
+    \Drupal::setContainer($container);
+
+    $account = $this->prophesize(AccountInterface::class);
+
+    $block1 = $this->prophesize(BlockPluginInterface::class);
+    $block1->access($account)->willReturn(TRUE);
+
+    // Building a block with empty content.
+    $block1->build()->willReturn(['#cache' => [ 'tags' => [ 0 => 'route']]]);
+    $block1->getConfiguration()->willReturn([]);
+    $block1->getPluginId()->willReturn([]);
+    $block1->getBaseId()->willReturn([]);
+    $block1->getDerivativeId()->willReturn([]);
+    $block1->getCacheTags()->willReturn(['test']);
+    $block1->getCacheMaxAge()->willReturn(0);
+    $block1->getCacheContexts()->willReturn([]);
+
+    $blocks = [
+      'top' => [
+        'block1' => $block1->reveal(),
+      ],
+    ];
+
+    $block_collection = $this->prophesize(BlockPluginCollection::class);
+    $block_collection->getAllByRegion()->willReturn($blocks);
+    $context_handler = $this->prophesize(ContextHandlerInterface::class);
+
+    $page = $this->prophesize(PageInterface::class);
+    $page->id()->willReturn('page_id');
+    $page->getCacheTags()->willReturn(['page:page_id']);
+
+    $page_executable = $this->prophesize(PageExecutable::class);
+    $page_executable->getPage()->willReturn($page->reveal());
+    $page_executable->getContexts()->willReturn([]);
+
+    $uuid_generator = $this->prophesize(UuidInterface::class);
+    $page_title = 'Page title';
+    $token = $this->prophesize(Token::class);
+    $token->replace($page_title, [])->willReturn($page_title);
+
+    $display_variant = new TestBlockDisplayVariant(['page_title' => $page_title], 'test', [], $context_handler->reveal(), $account->reveal(), $uuid_generator->reveal(), $token->reveal());
+    $display_variant->setBlockPluginCollection($block_collection->reveal());
+    $display_variant->setExecutable($page_executable->reveal());
+
+    // Empty block.
+    $expected_build = [
+      'regions' => [
+        'top' => [
+          '#prefix' => '<div class="block-region-top">',
+          '#suffix' => '</div>',
+          'block1' => [
+            '#markup' => '',
+            '#cache' => [
+              'keys' => [
+                'page_manager_page',
+                'page_id',
+                'block',
+                'block1',
+              ],
+              'tags' => [
+                'page:page_id',
+                'route',
+                'test',
+              ],
+              'contexts' => [],
+              'max-age' => 0,
+            ],
+          ],
+        ],
+      ],
+      '#title' => 'Page title',
+    ];
+
+    // Call build and the #pre_render callback, remove it from the render array
+    // to simplify the assertion.
+    $build = $display_variant->build();
+    $build['regions']['top']['block1'] = $display_variant->buildBlock($build['regions']['top']['block1']);
+    unset($build['regions']['top']['block1']['#pre_render']);
+    // Assert that the block return no content to be renderer.
+    $this->assertSame($expected_build, $build);
+  }
 
   /**
    * Tests the build() method when blocks can be cached.
@@ -338,3 +429,22 @@ public function providerTestSubmitConfigurationForm() {
   }
 
 }
+
+/**
+ * Wraps BlockDisplayVariant.
+ */
+class TestBlockDisplayVariant extends BlockDisplayVariant {
+
+  /**
+   * Sets the block plugin collection.
+   *
+   * @param \Drupal\page_manager\Plugin\BlockPluginCollection $block_plugin_collection
+   *
+   * @return $this
+   */
+  public function setBlockPluginCollection(BlockPluginCollection $block_plugin_collection) {
+    $this->blockPluginCollection = $block_plugin_collection;
+    return $this;
+  }
+
+}
