How do I hide an empty field if my custom field formatter removes all items?
Drupal adds the field wrapper only if the result returned by viewElements() contains at least one renderable child.

FormatterBase::view():

  public function view(FieldItemListInterface $items, $langcode = NULL) {
    ...
    $elements = $this-&gt;viewElements($items, $langcode);

    // If there are actual renderable children, use #theme =&gt; field, otherwise,
    // let access cacheability metadata pass through for correct bubbling.
    if (Element::children($elements)) {
      $entity = $items-&gt;getEntity();
      $entity_type = $entity-&gt;getEntityTypeId();
      $field_name = $this-&gt;fieldDefinition-&gt;getName();
      $info = [
        '#theme' =&gt; 'field',
        '#title' =&gt; $this-&gt;fieldDefinition-&gt;getLabel(),
        '#label_display' =&gt; $this-&gt;label,
        '#view_mode' =&gt; $this-&gt;viewMode,
        '#language' =&gt; $items-&gt;getLangcode(),
        '#field_name' =&gt; $field_name,
        '#field_type' =&gt; $this-&gt;fieldDefinition-&gt;getType(),
        '#field_translatable' =&gt; $this-&gt;fieldDefinition-&gt;isTranslatable(),
        '#entity_type' =&gt; $entity_type,
        '#bundle' =&gt; $entity-&gt;bundle(),
        '#object' =&gt; $entity,
        '#items' =&gt; $items,
        '#formatter' =&gt; $this-&gt;getPluginId(),
        '#is_multiple' =&gt; $this-&gt;fieldDefinition-&gt;getFieldStorageDefinition()-&gt;isMultiple(),
      ];

      $elements = array_merge($info, $elements);
    }

    return $elements;
  }


This means for the question if the field formatter removes all items the field is hidden.

However, field formatter and field preprocessing handle empty fields differently. If you only remove the first field item it is possible that the condition for an empty field has different results. See How to print all values of a multi-value field, except the first?