SVG/Tutorials/pointer-events

Aus SELFHTML-Wiki
< SVG‎ | Tutorials
Wechseln zu: Navigation, Suche
Die Eigenschaft pointer-events ermöglicht es, Elemente gezielt von Interaktionen durch Maus auszuschließen. Es war ursprünglich Teil der SVG-Spezifikation, um genauer zu kontrollieren, wo in einem Grafikobjekt ein Benutzer interagieren kann.

Sie verhindert mit einer Festlegung, dass …

  • Klicks eine Aktion auslösen
  • der cursor von auto auf pointer springt
  • :hover und active-Zustände ausgelöst werden
  • keine JavaScript click-Events gefeuert werden.


pointer-events in SVG

Das SVG pointer-events-Präsentationsattribut ermöglicht es, Elemente gezielt von Interaktionen durch Maus und teilweise auch Tastatur auszuschließen.[1]

Am häufigsten verwendete Werte sind:

  • auto, das Element verhält sich „ganz normal“ so, als ob pointer-events nicht gesetzt wäre, Voreinstellung
  • none, das Element reagiert nicht auf Interaktionen

Nur für SVG gültig sind:

  • visiblePainted
  • visibleFill
  • visibleStroke
  • visible
  • painted
  • fill
  • stroke
  • all

Dies ist insofern nützlich, wenn man in SVG ein Grafikobjekt aus mehreren Grundformen zeichnet und dies dann interaktiv, z.B. mit der Maus oder Tastatur auswählbar machen möchte.

Im Normalfall würde anfangs ein rect als Grundfläche für Hintergrundfarbe und Randlinie notiert werden. Darauf würden andere Grafikobjekte gezeichnet, die den Hintergrund verdecken. Um Mausaktionen bis zum untersten Element im Painting Stack durchzulassen, kann nun pointer-events="none" auf den Kreis gesetzt werden:

pointer-events:none → Mausaktionen durchlassen ansehen …
  <!--
  The circle will always intercept the mouse event.
  To change the stroke of the rect underneath you have
  to click outside the circle
  -->
  <rect tabindex="1" x="5" y="5" height="10" width="10" />
  <circle cx="10" cy="10" r="3" pointer-events="visiblePainted" />

  <!--
  The circle below will never catch a mouse event.
  The rect underneath will change stroke whether you
  are clicking on the circle or the rect itself
  -->
  <rect tabindex="2" x="20" y="5" height="10" width="10" />
  <circle cx="25" cy="10" r="3" pointer-events="none" />

Dieses Beispiel zeigt zwei Kreise, die aber nur eine farbige Randlinie haben. Der eigentliche Kreis ist durchsichtig fill: transparent; bzw. nicht gefüllt fill: none;

Ringe oder Kreise? ansehen …
#ring {
	fill: none;
	stroke: gold;
}
#full {
	fill: transparent;
	stroke: gold;
	pointer-events: visibleFill;
}
#full:hover {
	stroke: #337599;
}
rect:hover {
	stroke: #337599;
	stroke-width: .5;
}

Der linke Kreis lässt in seiner Kreisform die Events durch; im rechten Kreis wird mit pointer-events: visibleFill; nur die eigentliche Kreisfläche zum aktiven Element, obwohl sie transparent ist - ein :hover verändert die Farbe der Randlinie. Die Randlinie selbst lässt das :hover zum rect durch.

Beachte: Die Randlinie liegt genau auf dem Pfad der Kreislinie und ragt auf beiden Seiten aus dem Kreis heraus und in den Kreis hinein. Die innere Hälfte überdeckt die Füllfläche des Kreises.

Fazit

Dieses Attribut stammt aus einer Zeit, in der SVG-Dokumente als Standalone-SVGs zum Teil eigene DropDown-Navigationen hatten. Hier konnte so das unterste rect zur Klickfläche werden, ohne dass danach gezeichneter Text die Klickfläche verdeckt.

In HTML haben Elemente, die Text enthalten, ja im Element selbst Möglichkeiten Rand und Hintergrund festzulegen.

pointer-events in CSS

Seit einiger Zeit ist dieses Attribut auch in CSS übernommen worden.[2]

Hier gibt es nur drei Werte:

  • auto, das Element verhält sich „ganz normal“ so, als ob pointer-events nicht gesetzt wäre, Voreinstellung
  • none, das Element reagiert nicht auf Interaktionen
  • inherit, übernimmt den Wert des Elternelements
sich überlagernde Textblöcke ansehen …
    p.nicht_klickbar {
        pointer-events: none;
    }
    p.beispiel {
        border: thin solid #d5d5d5;
        ...
    }
    p.beispiel+p {
        position: relative;
        width: auto;
        padding: 3em;
        margin: 0 auto -7em;
        top: -8em;
        background-color: rgb(150 150 200 / 0.3);
        color: #c32e04;
    }

Die jeweils zweiten Absätze sind so verschoben, dass sie ihre Vorgänger überdecken. Im Normalfall ist deshalb der Text des darunterliegenden Elements nicht mit der Maus auswählbar. Wird für den überdeckenden Absatz festgelegt, dass dieser nicht auf Interaktionen mit der Maus reagieren soll, so hat dies zur Folge, dass nun der überdeckte Absatz mit der Maus bedienbar ist.

Beachte: Enthält das Element, welches nicht mehr auf Interaktionen mit der Maus reagieren soll, keine fokussierbaren Elemente, ist sein Inhalt auch nicht mit der Tastatur auswählbar.
Andererseits sind Buttons, die mit pointer-events funktionslos geschaltet werden, mit der Tastatur noch auswählbar. Hier ist disabled die bessere Alternative![3]

Achtung!

Hier wird ein Fix angeboten, der heilen soll, was eigentlich Konsequenz eines No-Go ist. Im Responsiven Webdesign sollten sich Elemente nie gegenseitig überdecken.
Ire Aderinokun schrieb schon 2018 There’s no reason to use pointer-events for HTML elements.[4]


Anwendungsbeispiel

dreistufiger Klickschalter ansehen …
<fieldset>
    <input id="tn-vielleicht" type="radio" name="teilnahme" value="0" checked="checked">
    <label for="tn-vielleicht">vielleicht</label>
    <input id="tn-nein" type="radio" name="teilnahme" value="-1">
    <label for="tn-nein">nein</label>
    <input id="tn-ja" type="radio" name="teilnahme" value="1">
    <label for="tn-ja">ja</label>
</fieldset>
label{
    position: absolute;
    display: block;
    left: 0;
    top: 0;
    width: 5em;
    padding: .5em;
    border: medium solid #c82f04;
    text-align: center;
}
:checked + label {
    z-index: 10;
    pointer-events: none;
}
:checked + label + input + label {
    pointer-events: none;
}
input {
    display: none;
}

Das Beispiel zeigt einen Button, der 3 Status haben kann. Technisch handelt es sich um eine Gruppe von drei Radiobuttons. Mithilfe absoluter Positionierung werden die drei label-Elemente übereinander positioniert.

Dasjenige Label, was zum ausgewählten Radiobutton gehört, wird durch die Angabe eines z-index sichtbar, für pointer-events werden sowohl dieses als auch das im Quelltext folgende label-Element unempfänglich gemacht.

Siehe auch

Referenz:

Weblinks

  1. svgwg.org PointerEventsProperty (SVG 2)
  2. MDN: pointer-events
  3. pointer-events (davidwalsh.name)
  4. bitsofco.de: There’s no reason to use pointer-events for HTML elements von Ire Aderinokun, 2018