Verwenden Sie Bilder wie Kontrollkästchen

163

Ich hätte gerne eine Alternative zu einem Standard-Kontrollkästchen - im Grunde möchte ich Bilder verwenden. Wenn der Benutzer auf das Bild klickt, wird es ausgeblendet und ein Kontrollkästchen überlagert.

Im Wesentlichen möchte ich etwas tun, wie es Recaptcha 2 tut, wenn Sie auf Bilder klicken, die bestimmte Kriterien erfüllen. Sie können hier eine Recaptcha-Demo sehen, aber manchmal können Sie Textfragen lösen, im Gegensatz zur Bildauswahl. Hier ist ein Screenshot:

Screenshot von Google Recaptcha

Wenn Sie auf eines der Bilder klicken (in diesem Fall mit einem Bild von Steak), wird das Bild, auf das Sie klicken, kleiner und das blaue Häkchen zeigt an, dass Sie es angekreuzt haben.

Angenommen, ich möchte genau dieses Beispiel reproduzieren.

Mir ist klar, dass ich 9 versteckte Kontrollkästchen haben und jQuery anhängen kann, sodass beim Klicken auf das Bild das versteckte Kontrollkästchen aktiviert / deaktiviert wird. Aber was ist mit dem Verkleinern des Bildes / Überlagern der Zecke?

bgs264
quelle
2
Sie können zwei identische Bilder haben: eines mit Häkchen und eines ohne Häkchen. Und ändern Sie Bilder auf Klick
Alex
22
@Alex Das wäre eine besonders unflexible Lösung.
Siguza
2
Haben Sie versucht, beim Klicken eine CSS-Klasse hinzuzufügen / zu entfernen, die die Bildgröße überschreibt und etwas :beforeMagie für das Häkchenbild bewirkt ?
Hexaholic
3
@Alex "Unflexibel" in dem Sinne, dass es viel mehr Arbeit erfordern würde, etwas zu ändern, z. B. ein neues Bild zur Sammlung hinzuzufügen oder das "angekreuzte" Symbol zu ändern, wenn dies nicht der Fall wäre, wenn der Effekt programmgesteuert bei erstellt wird Laufzeit.
Siguza
2
@Christian Das Ersetzen von Kontrollkästchen durch ein benutzerdefiniertes Kontrollkästchen ist eine beliebte Designentscheidung (auch wenn es sich nur um ein gestyltes Kontrollkästchen handelt). Für Entwickler, die sich damit befassen mussten, ist es auf jeden Fall von Interesse, gute / einfache Möglichkeiten zu finden. Und diese Frage (die das Ersetzen des Kontrollkästchens mit etwas anderem überlagert) macht es definitiv interessant. Beachten Sie insbesondere, dass die akzeptierte Antwort trotz der offensichtlichen Komplexität der Aufgabe überhaupt kein JS verwendet
Izkata

Antworten:

307

Reine semantische HTML / CSS-Lösung

Dies ist einfach selbst zu implementieren, es ist keine vorgefertigte Lösung erforderlich. Außerdem wird es Ihnen viel beibringen, da Sie mit CSS nicht allzu einfach zu sein scheinen.

Folgendes müssen Sie tun:

Ihre Kontrollkästchen müssen unterschiedliche idAttribute haben. Auf diese Weise können Sie eine Verbindung <label>mit dem forAttribut des Labels herstellen.

Beispiel:

<input type="checkbox" id="myCheckbox1" />
<label for="myCheckbox1"><img src="http://someurl" /></label>

Das Anhängen des Etiketts an das Kontrollkästchen löst ein Browserverhalten aus: Immer wenn jemand auf das Etikett (oder das darin enthaltene Bild) klickt, wird das Kontrollkästchen umgeschaltet.

Als nächstes blenden Sie das Kontrollkästchen aus, indem Sie es beispielsweise anwenden display: none;.

Jetzt müssen Sie nur noch den gewünschten Stil für Ihr label::beforePseudoelement festlegen (das als visuelles Ersatzelement für das Kontrollkästchen verwendet wird):

label::before {
    background-image: url(../path/to/unchecked.png);
}

In einem letzten kniffligen Schritt verwenden Sie den :checkedPseudo-Selektor von CSS, um das Bild zu ändern, wenn das Kontrollkästchen aktiviert ist:

:checked + label::before {
    background-image: url(../path/to/checked.png);
}

Die +( nebenstehende Geschwisterauswahl ) stellt sicher, dass Sie nur Beschriftungen ändern, die direkt auf das ausgeblendete Kontrollkästchen im Markup folgen.

Sie können dies optimieren, indem Sie beide Bilder in eine Spritemap einfügen und nur eine Änderung vornehmen, background-positionanstatt das Bild auszutauschen .

Natürlich müssen Sie das Etikett korrekt positionieren und anzuwenden display: block;und richtig eingestellt widthund height.

Bearbeiten:

Das Codepen-Beispiel und das Snippet, die ich nach diesen Anweisungen erstellt habe, verwenden dieselbe Technik, aber anstatt Bilder für die Kontrollkästchen zu verwenden, werden die Kontrollkästchen nur durch CSS ersetzt , wobei ::beforeauf dem Etikett ein erstellt wird, das nach dem Aktivieren vorhanden ist content: "✓";. Fügen Sie einige abgerundete Ränder und süße Übergänge hinzu und das Ergebnis ist wirklich sympathisch!

Hier ist ein funktionierender Codepen, der die Technik veranschaulicht und keine Bilder für das Kontrollkästchen benötigt:

http://codepen.io/anon/pen/wadwpx

Hier ist der gleiche Code in einem Snippet:

ul {
  list-style-type: none;
}

li {
  display: inline-block;
}

input[type="checkbox"][id^="cb"] {
  display: none;
}

label {
  border: 1px solid #fff;
  padding: 10px;
  display: block;
  position: relative;
  margin: 10px;
  cursor: pointer;
  -webkit-touch-callout: none;
  -webkit-user-select: none;
  -khtml-user-select: none;
  -moz-user-select: none;
  -ms-user-select: none;
  user-select: none;
}

label::before {
  background-color: white;
  color: white;
  content: " ";
  display: block;
  border-radius: 50%;
  border: 1px solid grey;
  position: absolute;
  top: -5px;
  left: -5px;
  width: 25px;
  height: 25px;
  text-align: center;
  line-height: 28px;
  transition-duration: 0.4s;
  transform: scale(0);
}

label img {
  height: 100px;
  width: 100px;
  transition-duration: 0.2s;
  transform-origin: 50% 50%;
}

:checked+label {
  border-color: #ddd;
}

:checked+label::before {
  content: "✓";
  background-color: grey;
  transform: scale(1);
}

:checked+label img {
  transform: scale(0.9);
  box-shadow: 0 0 5px #333;
  z-index: -1;
}
<ul>
  <li><input type="checkbox" id="cb1" />
    <label for="cb1"><img src="https://picsum.photos/seed/1/100" /></label>
  </li>
  <li><input type="checkbox" id="cb2" />
    <label for="cb2"><img src="https://picsum.photos/seed/2/100" /></label>
  </li>
  <li><input type="checkbox" id="cb3" />
    <label for="cb3"><img src="https://picsum.photos/seed/3/100" /></label>
  </li>
  <li><input type="checkbox" id="cb4" />
    <label for="cb4"><img src="https://picsum.photos/seed/4/100" /></label>
  </li>
</ul>

connexo
quelle
32
Froh, dass Sie es mögen! Fangen Sie an, mehr mit CSS herumzuspielen, es macht viel Spaß und CSS kann so viel mehr, als Sie wahrscheinlich jemals erwartet hätten (außer vertikaler Zentrierung, das ist einfach zu schwierig;)).
Connexo
1
Ja, und wenn Sie verstehen, wie es funktioniert, werden Sie in Zukunft jedes Mal nachdenken, wenn Sie eine DOM-Aktion per Mausklick wünschen. Und Sie dachten, Sie können nur auf :hover:) reagieren
Connexo
Das wird meine nächste Sache sein, die ich auf Pluralsight sehen werde - ein paar CSS-Sachen :)
bgs264
6
Das ist sehr nett! Ich habe ein kleines Problem festgestellt, wenn Sie zweimal auf dasselbe Etikett klicken und das Bild auswählen. Dies behebt es: codepen.io/anon/pen/jPmNjg
Ayesh K
1
Tick ​​hätte als SVG besser ausgesehen. Mit CSS-Inhalten sind Sie einigen schrecklichen Systemschriftarten ausgeliefert.
Adria
31

Reine CSS-Lösung

Es werden drei nette Geräte aufgerufen:

  1. Der :checkedSelektor
  2. Der ::beforePseudo-Selektor
  3. Die CSS- contentEigenschaft.

label:before {
  content: url("https://cdn1.iconfinder.com/data/icons/windows8_icons_iconpharm/26/unchecked_checkbox.png");
  position: absolute;
  z-index: 100;
}
:checked+label:before {
  content: url("https://cdn1.iconfinder.com/data/icons/windows8_icons_iconpharm/26/checked_checkbox.png");
}
input[type=checkbox] {
  display: none;
}
/*pure cosmetics:*/
img {
  width: 150px;
  height: 150px;
}
label {
  margin: 10px;
}
<input type="checkbox" id="myCheckbox1" />
<label for="myCheckbox1">
  <img src="https://encrypted-tbn2.gstatic.com/images?q=tbn:ANd9GcR0LkgDZRDTgnDrzhnXGDFRSItAzGCBEWEnkLMdnA_zkIH5Zg6oag">
</label>
<input type="checkbox" id="myCheckbox2" />
<label for="myCheckbox2">
  <img src="https://encrypted-tbn1.gstatic.com/images?q=tbn:ANd9GcRhJjGB3mQxjhI5lfS9SwXou06-2qT_0MjNAr0atu75trXIaR2d">
</label>
<input type="checkbox" id="myCheckbox3" />
<label for="myCheckbox3">
  <img src="https://encrypted-tbn3.gstatic.com/images?q=tbn:ANd9GcQuwWbUXC-lgzQHp-j1iw56PIgl_2eALrEENUP-ld72gq3s8cVo">
</label>

jcuenod
quelle
Wie ist es möglich, diesen Kontrollkästchen ein Optionsfeldverhalten hinzuzufügen? Ich meine, wenn Sie auf ein Bild klicken, wird das bereits ausgewählte Bild abgewählt.
Libertad
Wer sich die gleiche Frage wie @Libertad stellt, ändert einfach den Eingangstyp in Radio und gibt allen den gleichen Namen "Attribut". <input type="radio" name="myRadio" id="myRadio1" />Ändern Sie auch Ihr CSS, um die Kugel zu verbergen:input[type=radio]{display: none;}
Lou
8

Siehe dieses jQuery-Plugin: imgCheckbox (auf npm und bower )

Haftungsausschluss: Zur Lösung dieses Problems ist kein Javascript erforderlich. Die Spannung liegt zwischen Wartbarkeit und Effizienz des Codes. Es ist zwar kein Plugin (oder Javascript) erforderlich, aber es macht es sicher schneller zu erstellen und oft einfacher zu ändern.

Barebones-Lösung:

Mit sehr einfachem HTML (keine Unordnung mit Kontrollkästchen und Beschriftungen usw.):

<img class="checkable" src="http://lorempixel.com/100/100" />

Mit der toggleClass von jQuery können Sie eine selectedoder eine checkedKlasse für das clickEreignis aktivieren / deaktivieren :

$("img.checkable").click(function () {
    $(this).toggleClass("checked");
});

Überprüfte Elemente werden mit abgerufen

$(".checked")

Plus Coolness:

Sie können die Bilder basierend darauf formatieren, aber ein großes Problem ist, dass Sie ohne andere DOM-Elemente nicht einmal verwenden ::beforeund ::afterDinge wie Häkchen hinzufügen können. Die Lösung besteht darin, Ihre Bilder mit einem anderen Element zu versehen (und es ist sinnvoll, den Klick-Listener auch an das umschlossene Element anzuhängen).

$("img.checkable").wrap("<span class='fancychecks'>")

Dies lässt Ihr HTML wirklich sauber und Ihr js unglaublich lesbar. Schauen Sie sich das Snippet an ...

Verwenden des imgCheckbox jQuery Plugins :

Inspiriert von der obigen Lösung habe ich ein Plugin erstellt, das so einfach verwendet werden kann wie:

$("img").imgCheckbox();
  • Fügt die Daten für geprüfte Bilder in Ihr Formular ein
  • Unterstützt benutzerdefinierte Häkchen
  • Unterstützt benutzerdefiniertes CSS
  • Unterstützt vorausgewählte Elemente
  • Unterstützt Radiogruppen anstelle des einfachen Umschaltens von Bildern
  • Hat Ereignisrückrufe
  • Sinnvolle Standardeinstellungen
  • Leicht und super einfach zu bedienen

Sehen Sie es in Aktion (und sehen Sie die Quelle )

jcuenod
quelle
Ich mag diesen Ansatz auch, aber er hat eine Reihe von Nachteilen, die erwähnenswert sind. Der größte ist folgender: Angenommen, der Benutzer soll Bilder auswählen, die vom Benutzer auf diese Weise gegebenen Informationen sollen sicherlich irgendwie verarbeitet werden es über einen AJAX-Anruf oder über ein Formular senden. Für die Voraussetzungen einer weiteren Verarbeitung der vom Benutzer gegebenen Informationen ist es nur eine natürliche, semantische Methode, Kontrollkästchen zu haben, in denen eine Reihe von Auswahlmöglichkeiten reflektiert und verarbeitet werden müssen.
Connexo
Dies ist wahr, es steht auf meiner Aufgabenliste für das Plugin - um die Übermittlung von Formularen zu entführen und die Daten in das Formular einzufügen. Aber Sie haben Recht, Kontrollkästchen sind semantisch für Formulare
jcuenod
Ich habe versucht, Ihr Plugin zu verwenden, aber wenn ich nach der Initialisierung weitere Bilder hinzufüge, scheint es keine Möglichkeit zu geben, die vorherige Instanz zu zerstören, damit die neuen Bilder aufgenommen werden können
Ian Kim
@ IanKim interessanter Anwendungsfall, können Sie mehr darüber erklären, was Sie in einer Ausgabe auf Github versuchen? github.com/jcuenod/imgCheckbox
jcuenod
Es ist ein tolles Plugin! Bitte veröffentlichen Sie ein Webjar =)
naXa
6

Ich würde eine zusätzliche div anhängen mit position: relative;und class="checked"die die gleiche Breite / Höhe hat wie die Bildposition hat und als in left: 0; top: 0;das Symbol enthält. Es beginnt mit display: none;.

Jetzt können Sie das clickEreignis hören:

$( '.captcha_images' ).click( function() {
    $(this + '.checked').css( 'display', 'block' );
    $(this).animate( { width: '70%', height: '70%' } );
});

Auf diese Weise können Sie das Symbol erhalten und die Bildgröße auf eine kleinere Größe ändern.

Hinweis: Ich wollte Ihnen nur die "Logik" hinter meinen Gedanken zeigen. Dieses Beispiel funktioniert möglicherweise nicht oder enthält einige Fehler.

Cagatay Ulubay
quelle
Die Technik, die ich demonstriert habe, ist so einfach und robust, dass sie sogar häufig in Situationen angewendet wird, in denen Sie semantisch keine Kontrollkästchen haben, z. B. beim Umschalten der Anzeige anderer Elemente und dergleichen. Dies ist der Anwendungsfall, in dem es nicht nur die einfachste und flexibelste Lösung ist, sondern auch die semantisch beste.
Connexo
2
Ja, du hast Recht. Zuerst wollte ich auf Ihre erste Antwort hinweisen und sie verbessern (vor dem Bearbeiten), weil ich No-JS und nette semantische Methoden mag, aber dann habe ich gelesen, dass das OP etwas in jQuery will, also habe ich meine Antwort geändert. Ich erinnere mich, wo ich eine Ablehnung bekommen habe, weil das OP keine "bessere" oder "richtige" Lösung wollte, sondern genau die Art und Weise, wie er schrieb. Vielleicht gibt es nur etwas, das ich überlesen oder nicht verstanden habe oder das vom OP abhängt?
Cagatay Ulubay
2

Ich habe festgestellt, dass andere Antworten entweder nicht verwendet werden <label>(warum nicht?) Oder Übereinstimmungen forund idAttribute erfordern . Dies bedeutet, dass Ihr Code nicht funktioniert, wenn Sie nicht übereinstimmende IDs haben, und Sie müssen daran denken, jedes Mal eindeutige IDs zu erstellen.

Wenn Sie das inputmit display:noneoder ausblenden visibility:hidden, konzentriert sich der Browser nicht darauf.

Ein Kontrollkästchen und sein Text (oder in diesem Fall das Bild) können in ein Etikett eingeschlossen werden:

.fancy-checkbox-label > input[type=checkbox] {
  position: absolute;
  opacity: 0;
  cursor: inherit;
}
.fancy-checkbox-label {
  font-weight: normal;
  cursor: pointer;
}
.fancy-checkbox:before {
  font-family: FontAwesome;
  content: "\f00c";
  background: #fff;
  color: transparent;
  border: 3px solid #ddd;
  border-radius: 3px;
  z-index: 1;
}
.fancy-checkbox-label:hover > .fancy-checkbox:before,
input:focus + .fancy-checkbox:before {
  border-color: #bdbdff;
}
.fancy-checkbox-label:hover > input:not(:checked) + .fancy-checkbox:before {
  color: #eee;
}
input:checked + .fancy-checkbox:before {
  color: #fff;
  background: #bdbdff;
  border-color: #bdbdff;
}
.fancy-checkbox-img:before {
  position: absolute;
  margin: 3px;
  line-height: normal;
}
input:checked + .fancy-checkbox-img + img {
  transform: scale(0.9);
  box-shadow: 0 0 5px #bdbdff;
}
<link href="https://maxcdn.bootstrapcdn.com/font-awesome/4.6.3/css/font-awesome.min.css" rel="stylesheet" integrity="sha384-T8Gy5hrqNKT+hzMclPo118YTQO6cYprQmhrYwIiQ/3axmI1hQomh7Ud2hPOy8SP1" crossorigin="anonymous">
<p>
  <label class="fancy-checkbox-label">
    <input type="checkbox">
    <span class="fancy-checkbox"></span>
    A normal checkbox
  </label>
</p>
<p>
  <label class="fancy-checkbox-label">
    <input type="checkbox">
    <span class="fancy-checkbox fancy-checkbox-img"></span>
    <img src="http://placehold.it/150x150">
  </label>
</p>

rybo111
quelle
1

Hier ein kurzes Beispiel für die Auswahl eines Bildes wie ein Kontrollkästchen

Beispiel mit Knockout.js aktualisiert:

var imageModel = function() {
    this.chk = ko.observableArray();
};
ko.applyBindings(new imageModel());
    input[type=checkbox] {
        display:none;
      }
 
  input[type=checkbox] + label
   {
       display:inline-block;
        width:150px;
        height:150px;
        background:#FBDFDA;
        border:none;
   }
   
   input[type=checkbox]:checked + label
    {
        background:#CFCFCF;
        border:none;
        position:relative;
        width:100px;
        height:100px;
        padding: 20px;
    }

   input[type=checkbox]:checked + label:after
    {
        content: '\2713';
        position:absolute;
        top:-10px;
        right:-10px;
        border-radius: 10px;
        width: 25px;
        height: 25px;
        border-color: white;
        background-color: blue;
    }
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.0.0/knockout-min.js"></script>
<input type='checkbox' name='image1' value='image1' id="image1" data-bind="checked: chk"/><label for="image1"></label><label for="image1"><img class='testbtn'/></label>

<div data-bind="html: chk"></div>

YaBCK
quelle
1
Obwohl mir Ihr Ansatz gefällt, wäre es für die meisten hilfreich zu sagen, dass Sie in Ihrem Beispiel Knockout.js verwenden.
Connexo
@connexo Cheers, gerade aktualisiert, um Beispiel mit Knockout.js
YaBCK
0

Erweiterung der akzeptierten Antwort für alle, die WordPress & GravityForms zum Generieren ihrer Formulare verwenden und Kontrollkästchenfelder automatisch mit einer Liste von Posts und der zugehörigen empfohlenen Miniaturansicht füllen möchten

// Change '2' to your form ID
add_filter( 'gform_pre_render_2', 'populate_checkbox' );
add_filter( 'gform_pre_validation_2', 'populate_checkbox' );
add_filter( 'gform_pre_submission_filter_2', 'populate_checkbox' );
add_filter( 'gform_admin_pre_render_2', 'populate_checkbox' );

function populate_checkbox( $form ) {

    foreach( $form['fields'] as &$field )  {

        // Change '41' to your checkbox field ID
        $field_id = 41;
        if ( $field->id != $field_id ) {
            continue;
        }

        // Adjust $args for your post type
        $args = array(
                'post_type' => 'pet',
                'post_status' => 'publish',
                'posts_per_page' => -1,
                'tax_query' => array(
                        array(
                                'taxonomy' => 'pet_category',
                                'field' => 'slug',
                                'terms' => 'cat'
                        )
                )
        );

        $posts = get_posts( $args );

        $input_id = 1;

        foreach( $posts as $post ) {

            $feat_image_url = wp_get_attachment_image( get_post_thumbnail_id( $post->ID ), 'thumbnail' );
            $feat_image_url .= '<br />' . $post->post_title;

            if ( $input_id % 10 == 0 ) {
                $input_id++;
            }

            $choices[] = array( 'text' => $feat_image_url, 'value' => $post->post_title );
            $inputs[] = array( 'label' => $post->post_title, 'id' => "{$field_id}.{$input_id}" );

            $input_id++;
        }

        $field->choices = $choices;
        $field->inputs = $inputs;

    }

    return $form;
}

Und das CSS:

.gform_wrapper .gfield_checkbox li[class^="gchoice_2_41_"] {
    display: inline-block;
}

.gform_wrapper .gfield_checkbox li input[type="checkbox"][id^="choice_2_41_"] {
    display: none;
}


.gform_wrapper .gfield_checkbox li label[id^="label_2_41_"] {
    border: 1px solid #fff;
    padding: 10px;
    display: block;
    position: relative;
    margin: 10px;
    cursor: pointer;
    -webkit-touch-callout: none;
    -webkit-user-select: none;
    -khtml-user-select: none;
    -moz-user-select: none;
    -ms-user-select: none;
    user-select: none;
}

label[id^="label_2_41_"]:before {
    font-family: "font-icons";
    font-size: 32px;
    color: #1abc9c;
    content: " ";
    display: block;
    background-color: transparent;
    position: absolute;
    top: -5px;
    left: -5px;
    width: 25px;
    height: 25px;
    text-align: center;
    line-height: 28px;
    transition-duration: 0.4s;
    transform: scale(0);
}

label[id^="label_2_41_"] img {
    transition-duration: 0.2s;
    transform-origin: 50% 50%;
}

:checked + label[id^="label_2_41_"] {
    border-color: #ddd;
}

/* FontAwesome tick */
:checked + label[id^="label_2_41_"]:before {
    content: "\e6c8";
    background-color: transparent;
    transform: scale(1);
}

:checked + label[id^="label_2_41_"] img {
    transform: scale(0.9);
    box-shadow: 0 0 5px #333;
    z-index: 0;
}
essexboyracer
quelle