Um unerwartete Abstände um eine SVG-use-Instanz zu entfernen, stelle fest, ob sie durch die Quell-viewBox, die Anpassung des Seitenverhältnisses oder die umgebende CSS-Zeilenbox entstehen. Diese Anleitung zeigt, wie du jede Ursache diagnostizierst und behebst und dabei vorhersehbare Platzierungskoordinaten beibehältst.

Die Aufgabe besteht in einer kleinen Bearbeitung einer Desktop-Webseite: Positioniere eine wiederverwendbare Form präzise innerhalb eines SVG und passe anschließend das umgebende HTML-Layout wie gewünscht an. Du kannst die Beispiele in einem einfachen Texteditor auf deinem Mac nachvollziehen und die gespeicherte HTML-Datei in einem aktuellen Desktop-Browser öffnen.

Welches Koordinatensystem bestimmt den Abstand?

Es gibt drei Begrenzungen, die du überprüfen solltest: die CSS-Box des äußeren SVG-Elements, den für ein referenziertes Symbol verwendeten Viewport und die eigentliche Form innerhalb dieses Symbols. Das W3C unterscheidet ausdrücklich zwischen einem SVG-Viewport und dem CSS-Viewport des Browsers. Eine viewBox bildet SVG-Benutzerkoordinaten auf einen SVG-Viewport ab; sie beschreibt nicht das Browserfenster. Koordinatensysteme, Transformationen und Einheiten — SVG 2

Zum Beispiel legt x="20" bei einem use-Element einen Versatz in dessen SVG-Koordinatensystem fest. Das bedeutet nicht, dass der Abstand zum linken Rand des Browserfensters 20 CSS-Pixel beträgt. Skalierung und Transformationen übergeordneter Elemente können die Position dieses Versatzes auf der Seite verändern. Die SVG-Spezifikation beschreibt die Positionierung von use als zusätzliche Translation, deren Verhalten sich von dem des CSS-Boxlayouts unterscheidet. Dokumentstruktur — SVG 2

Beginne mit dieser Entscheidungstabelle. Sie zeigt eine diagnostische Abfolge, die sich aus den dokumentierten Layoutmechanismen ergibt, und keine Liste austauschbarer Korrekturen.

Beobachtung Zuerst prüfen Mögliche Korrektur
Ein schmaler Streifen unter dem gesamten SVG Inline-Formatierung und Zeilenhöhe des übergeordneten Elements Ein eigenständiges SVG als Blockelement festlegen oder seine Inline-Ausrichtung anpassen
Leerer Raum innerhalb jeder wiederholten Grafik Formkoordinaten im Verhältnis zur viewBox des Symbols Quellgrenzen enger setzen, falls der Einzug unbeabsichtigt ist
Zusätzlicher Abstand auf zwei Seiten einer Symbolinstanz Instanzabmessungen im Verhältnis zum viewBox Verhältnisse angleichen oder eine bewusste Anpassungsstrategie wählen
Lokal korrekt platziert, aber auf der Seite falsch positioniert SVG-Benutzerkoordinaten im Verhältnis zu den Koordinaten des Browser-Viewports Koordinaten umrechnen, bevor du x und y zuweist
Änderungen der Instanzabmessungen bewirken nichts Das von href adressierte Element Ein Symbol mit definierendem Viewport für die Anpassung verwenden oder die Geometrie transformieren

Den Abstand mit einem vollständigen lokalen Beispiel reproduzieren

Speichere das folgende vollständige Dokument in einem einfachen Texteditor als svg-spacing.html und öffne es anschließend in deinem Browser. Es verwendet nur künstliche Beschriftungen und Rechtecke, keine Bibliotheken oder externen Dateien. Die hellen Rechtecke markieren die vorgesehenen Instanz-Viewports; die dunkleren Rechtecke zeigen die wiederverwendeten Grafiken.

<!doctype html>
<html lang="en">
<head>
  <meta charset="utf-8">
  <title>SVG spacing example</title>
  <style>
    body {
      margin: 24px;
      font: 16px system-ui, sans-serif;
    }
    #canvas {
      display: block;
      width: 320px;
      height: 200px;
      outline: 1px solid #687580;
      background: #fff;
    }
    .viewport-guide { fill: #e4edf2; }
    .artwork { fill: #356b8c; }
    text { fill: #253744; font-size: 14px; }
  </style>
</head>
<body>
  <p>Two instances with different source bounds and fitting dimensions.</p>
  <svg id="canvas" xmlns="http://www.w3.org/2000/svg"
       width="320" height="200" viewBox="0 0 320 200"
       role="img" aria-labelledby="drawing-title">
    <title id="drawing-title">Padded and tightly fitted rectangles</title>
    <defs>
      <symbol id="padded" viewBox="0 0 100 100">
        <rect id="source-shape" class="artwork"
              x="20" y="20" width="60" height="60" />
      </symbol>
      <symbol id="tight" viewBox="20 20 60 60">
        <rect class="artwork"
              x="20" y="20" width="60" height="60" />
      </symbol>
    </defs>

    <rect class="viewport-guide"
          x="20" y="20" width="120" height="60" />
    <use href="#padded" x="20" y="20" width="120" height="60" />
    <text x="160" y="55">Padded source</text>

    <rect class="viewport-guide"
          x="20" y="110" width="60" height="60" />
    <use id="tight-instance" href="#tight"
         x="20" y="110" width="60" height="60" />
    <text x="110" y="145">Tight source</text>
  </svg>
</body>
</html>

Beide Instanzen legen ihre Abmessungen ausdrücklich fest. So musst du dich bei der Untersuchung des Abstands nicht auf eine implizite Größenbestimmung verlassen. MDN beschreibt use als Wiederverwendung referenzierter SVG-Inhalte und weist darauf hin, dass width und height die Anpassung beeinflussen, wenn das Ziel ein SVG oder ein Symbol mit einer viewBox ist. Das Beispiel verwendet das aktuelle Attribut href. MDN: use

Berechnen, wo das erste Rechteck tatsächlich beginnt

Die erste Quelle hat eine viewBox von 100 × 100, aber ihr Rechteck umfasst nur die Koordinaten 20 bis 80 in beiden Richtungen. Der angeforderte Instanz-Viewport ist 120 × 60. Bei der standardmäßigen Anpassung xMidYMid meet ist die Skalierung der kleinere Wert aus 120 / 100 und 60 / 100: 0.6. Die skalierte ViewBox nimmt 60 × 60 ein, sodass auf jeder Seite horizontal 30 Einheiten frei bleiben. Das entspricht dem W3C-Algorithmus zur Viewport-Transformation. SVG 2: Die äquivalente Transformation eines SVG-Viewports berechnen

Für diese beispielhaften Eingabewerte beginnt das gezeichnete Rechteck horizontal bei 20 + 30 + 20 × 0.6 = 62 und vertikal bei 20 + 20 × 0.6 = 32. Seine Größe beträgt in jeder Richtung 60 × 0.6 = 36. Die Berechnung wurde mit einer kleinen deterministischen Rechnung überprüft; dies sind berechnete Werte, keine Messungen aus einem Browser-Test.

Die zweite Instanz ändert zwei unabhängige Eingaben: Ihre Quellgrenzen werden zu 20 20 60 60, und ihr Instanz-Viewport wird auf 60 × 60 gesetzt. Das Rechteck füllt daher diesen Viewport aus und beginnt bei der SVG-Koordinate (20, 110). Um die Ursachen selbst voneinander abzugrenzen, ändere jeweils nur eine Eingabe.

Wie entfernst du Abstände innerhalb der Instanz?

Unbeabsichtigte Abstände in den Quellgrenzen korrigieren

Eine viewBox enthält vier Zahlen: minimaler x-Wert, minimaler y-Wert, Breite und Höhe. Ihr Ursprung muss nicht bei null liegen. Im Beispiel beschreibt viewBox="20 20 60 60" die vorhandenen Grenzen des Rechtecks, ohne dessen Geometrie neu zu schreiben. MDN: viewBox

Bevor du die Grenzen einer echten Grafik enger setzt, entscheide, ob ihr Einzug beabsichtigt ist. Eine Reihe wiederverwendbarer Formen kann ein gemeinsames Koordinatensystem nutzen, damit ihre visuellen Größen und Positionen einheitlich bleiben. Wenn du jedes Symbol einzeln enger begrenzt, können sich diese Beziehungen ändern. Behalte gemeinsame Grenzen bei, wenn diese Einheitlichkeit Teil des Designs ist.

Zur Untersuchung der Geometrie liefert getBBox() Begrenzungen in SVG-Benutzerkoordinaten. Standardmäßig berücksichtigt es weder Konturen noch Marker und bezieht Transformationen des Zielelements oder seiner übergeordneten Elemente nicht ein. Daher reicht eine nur die Füllung berücksichtigende Bounding-Box nicht aus, um Konturen oder transformierte Grafiken zuverlässig zuzuschneiden. MDN: SVGGraphicsElement getBBox()

Festlegen, wie unterschiedliche Seitenverhältnisse angepasst werden

Selbst eng begrenzte Grafiken können von Freiraum umgeben sein, wenn eine quadratische Quelle in einen breiten Viewport eingepasst wird. Wähle die Strategie entsprechend dem gewünschten Ergebnis. Verwende preserveAspectRatio für die interne Anpassung auf dem referenzierten Symbol oder auf dem äußeren SVG, wenn du die äußere Koordinatenabbildung untersuchst. MDN: preserveAspectRatio

Auswahl Ergebnis und Bedingung
Übereinstimmende Seitenverhältnisse von Quelle und Viewport Vermeidet Abstände durch die Anpassung des Seitenverhältnisses und erhält die Proportionen
xMidYMid meet Zeigt die gesamte ViewBox zentriert an; unterschiedliche Seitenverhältnisse lassen Freiraum
xMinYMin meet Verschiebt die angepasste ViewBox nach links oben; der übrige Freiraum bleibt bestehen
none Ermöglicht nicht gleichmäßige Skalierung; aus einem Quadrat kann ein Rechteck werden
xMidYMid slice Füllt den Viewport aus, wobei Teile des Quellinhalts über ihn hinausragen; die Sichtbarkeit hängt vom Zuschneiden ab

Eine Änderung der Ausrichtung verschiebt den durch die Anpassung entstehenden Freiraum. Einen bereits in der Quellgeometrie enthaltenen Einzug entfernt sie nicht. Ebenso ist slice ungeeignet, wenn der gesamte Quellinhalt innerhalb des Viewports bleiben muss. Diese Unterschiede entsprechen den MDN-Definitionen von Ausrichtung, meet, slice und nicht gleichmäßiger Anpassung. MDN: preserveAspectRatio

Das Referenzziel prüfen, wenn Änderungen der Abmessungen keine Wirkung zeigen

Eine einfache Gruppe oder ein Pfad erhält nicht allein dadurch einen Viewport für die Anpassung, dass ein use-Element darauf verweist. Das W3C erklärt, dass das Instanz-width und das Instanz-height keine Wirkung haben, wenn das referenzierte Element keinen neuen Viewport definiert. Für eine vorhersehbare Anpassung pro Instanz solltest du die wiederverwendbare Geometrie wie oben in ein Symbol mit expliziten Grenzen setzen. Für eine direkte geometrische Skalierung verwendest du eine Transformation und berücksichtigst deren Auswirkung auf die Positionierung. SVG 2: Layout wiederverwendeter Grafiken

Wie entfernst du den Streifen unter dem äußeren SVG?

Ein Abstand außerhalb des SVG kann durch die Inline-Formatierung in HTML entstehen. WHATWG erlaubt SVG-Elemente in phrasierenden Inhalten; die umgebende Seite kann sie daher neben Text platzieren. Zeilenboxen in CSS umfassen Schriftmetriken ober- und unterhalb der Grundlinie. Deshalb kann eine Inline-Grafik unter ihrer Box sichtbaren Freiraum lassen. HTML-Standard: SVG, CSS 2: Berechnung der Zeilenhöhe

Das vollständige Beispiel setzt für #canvas bereits display: block, wodurch das SVG nicht an einer Inline-Zeilenbox teilnimmt. Behalte diese Regel für eine eigenständige Zeichnung bei. Um den Mechanismus zu untersuchen, ändere sie vorübergehend zu display: inline und untersuche die umgebende Zeile.

Wenn ein SVG neben Text stehen muss, probiere vertical-align: bottom auf dem äußeren SVG aus und überprüfe die resultierende Textausrichtung. Diese Eigenschaft richtet eine Inline-Box innerhalb ihrer Zeile aus. Sie ändert weder Symbolgrenzen noch die interne Anpassung. Andere Inhalte und die Zeilenhöhe des übergeordneten Elements können weiterhin die Gesamthöhe der Zeile bestimmen. MDN: vertical-align

Betrachte diese CSS-Deklarationen als Alternativen für das äußere SVG und nicht als Korrekturen, die du kumulativ auf jede Instanz anwenden solltest:

/* Standalone drawing */
#canvas {
  display: block;
}

/* Alternative when the drawing must stay inline */
/*
#canvas {
  display: inline;
  vertical-align: bottom;
}
*/

Was, wenn deine Koordinaten aus dem Browser-Viewport stammen?

getBoundingClientRect() gibt die Position eines Elements relativ zum Browser-Viewport in CSS-Pixeln an. Diese Position ändert sich, wenn du die Seite scrollst. Diese Werte gehören zu einem anderen Koordinatenraum als SVG-Benutzerkoordinaten. Daher ist es im Allgemeinen falsch, left und top direkt in x und y einer Instanz zu kopieren. MDN: Element getBoundingClientRect()

Wenn die Eingabe ein Punkt im Browser-Viewport ist, verwende eine Koordinatentransformation. getScreenCTM() liefert die Transformationsmatrix des SVG, und durch Anwendung ihrer inversen Matrix wird der Punkt zurück in die lokalen Koordinaten des ausgewählten Elements umgerechnet. Die Methode matrixTransform() eines Punkts führt diese Umrechnung aus. MDN: getScreenCTM(), MDN: matrixTransform()

Der folgende Konsolen-Code ist eine optionale Erweiterung des obigen vollständigen Dokuments. Er rechnet den Browser-Viewport-Punkt (100, 150) in die Benutzerkoordinaten des äußeren SVG um und verschiebt die eng begrenzte Instanz dorthin. Er setzt voraus, dass die unveränderte Instanz aus dem Beispiel ein direktes Kindelement dieses SVG bleibt.

(() => {
  const canvas = document.getElementById("canvas");
  const instance = document.getElementById("tight-instance");
  if (!canvas || !instance) {
    throw new Error("Open the complete SVG spacing example first.");
  }

  const matrix = canvas.getScreenCTM();
  if (!matrix) {
    throw new Error("The SVG coordinate matrix is unavailable.");
  }

  const viewportPoint = new DOMPoint(100, 150);
  const localPoint = viewportPoint.matrixTransform(matrix.inverse());
  if (!Number.isFinite(localPoint.x) || !Number.isFinite(localPoint.y)) {
    throw new Error("The SVG coordinate matrix cannot be inverted.");
  }

  instance.setAttribute("x", String(localPoint.x));
  instance.setAttribute("y", String(localPoint.y));
})();

Die Prüfung auf endliche Zahlen ist wichtig, weil eine nicht invertierbare Matrix NaN-Komponenten ergibt. Berechne die Matrix erneut, wenn du nach Änderungen am Layout oder Scrollen einen neuen Punkt umrechnest. Wenn sich deine Instanz in einer transformierten Gruppe befindet, rechne sie in das Koordinatensystem dieser übergeordneten Gruppe um. Dieser Code wurde anhand der API-Dokumentation geprüft, aber während der Recherche nicht in einem Browser ausgeführt. MDN: DOMMatrixReadOnly inverse()

Prüfe zum Schluss die drei Begrenzungen getrennt: die Box des äußeren SVG, den angepassten Viewport des Symbols und die eigenen Grenzen der Grafik. Korrigiere die Begrenzung, die den unerwünschten Abstand verursacht, und überprüfe das Ergebnis anschließend bei der vorgesehenen Seitengröße. So erhältst du eine vorhersehbare Platzierung, ohne einen unerklärlichen Abstand mit willkürlichen Versätzen ausgleichen zu müssen.

Quellen