How can I control block visibility with code?
A working code snippet how to use hook_block_access(). Here I retrieve the condition from a field of the current node:
use Drupal\block\Entity\Block;
use Drupal\Core\Access\AccessResult;
use Drupal\Core\Session\AccountInterface;
use Drupal\node\NodeInterface;

/**
 * Implements hook_block_access().
 */
function MYMODULE_block_access(Block $block, $operation, AccountInterface $account) {

  if ($operation === 'view' &amp;&amp; $block-&gt;getPluginId() === 'MYBLOCK') {

    $node = \Drupal::routeMatch()-&gt;getParameter('node');

    $hero_image_exists = FALSE;

    if ($node instanceof NodeInterface) {
      if ($node-&gt;hasField('field_hero_image')) {
        if (!$node-&gt;get('field_hero_image')-&gt;isEmpty()) {
          $hero_image_exists = TRUE;
        }
      }
    }

    return AccessResult::forbiddenIf($hero_image_exists === FALSE)-&gt;addCacheableDependency($block);
  }

  return AccessResult::neutral();
}


Thanks @Insasse for sharing the following gem in the comments. For programmatically created custom blocks you can control visibility directly from inside the block class via blockAccess():

class MyBlock extends BlockBase {
  /**
   * {@inheritdoc}
   */
  public function build() {
    return [
      '#markup' =&gt; $this-&gt;t('This is a simple block!'),
    ];
  }

  /**
   * {@inheritdoc}
   */
  protected function blockAccess(AccountInterface $account) {
    return AccessResult::allowedIfHasPermission($account, 'access content');
  }

}


Source: How to Programmatically Create a Block in Drupal 8