J'aimerais avoir une alternative à une case à cocher standard. En gros, j'aimerais utiliser des images. Lorsque l'utilisateur clique sur l'image, la fait fondre et la superpose.
En gros, je veux faire quelque chose comme Recaptcha 2 quand il vous permet de cliquer sur des images qui répondent à certains critères. Vous pouvez voir une démonstration de Recaptcha ici mais cela peut parfois vous amener à résoudre des questions de texte, par opposition à la sélection d'images. Alors, voici une capture d'écran:
Lorsque vous cliquez sur l'une des images (dans ce cas, contenant une image de steak), la taille de l'image sur laquelle vous cliquez est réduite et la coche bleue apparaît, indiquant que vous l'avez cochée.
Disons que je veux reproduire cet exemple exact.
Je me rends compte que je peux avoir 9 cases à cocher cachées et attacher un peu de jQuery afin que lorsque je clique sur l'image, elle sélectionne/désélectionne la case à cocher masquée. Mais qu'en est-il de la réduction de l'image/superposition de la tique?
C’est simple à mettre en œuvre, aucune solution préconçue n’est nécessaire. En outre, il vous en apprendra beaucoup car vous ne semblez pas très facile avec CSS.
Vos cases à cocher doivent avoir des attributs id
distincts. Cela vous permet de connecter un <label>
à l'aide de l'attribut for
- de l'étiquette.
Exemple:
<input type="checkbox" id="myCheckbox1" />
<label for="myCheckbox1"><img src="http://someurl" /></label>
Si vous associez l’étiquette à la case à cocher, le navigateur se comportera de la manière suivante: chaque fois que quelqu'un cliquera sur l’étiquette (ou sur l’image qu’elle contient), la case à cocher sera cochée.
Ensuite, vous masquez la case en y appliquant par exemple display: none;
.
Il ne vous reste plus qu'à définir le style souhaité pour votre pseudo-élément label::before
(qui sera utilisé comme élément de remplacement visuel de case à cocher):
label::before {
background-image: url(../path/to/unchecked.png);
}
Dans une dernière étape délicate, vous utilisez le pseudo-sélecteur :checked
de CSS pour changer l'image lorsque la case à cocher est cochée:
:checked + label::before {
background-image: url(../path/to/checked.png);
}
Le +
(sélecteur de fratrie adjacent) garantit que vous ne modifiez que les étiquettes qui suivent directement la case à cocher masquée dans la balise.
Vous pouvez optimiser cela en plaçant les deux images dans un spritemap et en appliquant uniquement une modification de background-position
au lieu de permuter l'image.
Bien sûr, vous devez positionner correctement l'étiquette, appliquer display: block;
et définir les correctes width
et height
.
L'exemple de code et le fragment, que j'ai créés après ces instructions, utilisent la même technique, mais au lieu d'utiliser des images pour les cases à cocher, les remplacements de cases à cocher sont effectués uniquement avec CSS, créant un ::before
sur l'étiquette qui, une fois cochée , a content: "✓";
. Ajoutez des bordures arrondies et des transitions douces et le résultat est vraiment sympathique!
Voici un codepen fonctionnel qui présente la technique et ne nécessite pas d'images pour la case à cocher:
Voici le même code dans un extrait:
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="http://lorempixel.com/100/100" /></label>
</li>
<li><input type="checkbox" id="cb2" />
<label for="cb2"><img src="http://lorempixel.com/101/101" /></label>
</li>
<li><input type="checkbox" id="cb3" />
<label for="cb3"><img src="http://lorempixel.com/102/102" /></label>
</li>
<li><input type="checkbox" id="cb4" />
<label for="cb4"><img src="http://lorempixel.com/103/103" /></label>
</li>
</ul>
Il existe trois périphériques ordonnés invoqués:
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>
Voir ce plugin jQuery: imgCheckbox (sur npm et bower)
Déni de responsabilité: Aucun javascript n'est nécessaire pour résoudre ce problème. La tension est entre maintenabilité et efficacité du code. Bien qu'il n'y ait pas besoin de plugin (ni de javascript), cela rend la création plus rapide et souvent plus facile à modifier.
Avec très simple HTML (aucun problème avec les cases à cocher, les étiquettes, etc.):
<img class="checkable" src="http://lorempixel.com/100/100" />
Vous pouvez utiliser toggleClass de jQuery pour activer/désactiver une classe selected
ou checked
sur l'événement click
:
$("img.checkable").click(function () {
$(this).toggleClass("checked");
});
Les articles cochés sont récupérés avec
$(".checked")
Vous pouvez styliser les images à partir de cela, mais un gros problème est que sans autres éléments DOM, vous ne pouvez même pas utiliser ::before
et ::after
pour ajouter des éléments tels que des coches. La solution consiste à envelopper vos images avec un autre élément (et il est également logique d'attacher l'auditeur de clic à l'élément enveloppé).
$("img.checkable").wrap("<span class='fancychecks'>")
Cela laisse votre code HTML vraiment propre et votre texte incroyablement lisible. Jetez un coup d'œil à l'extrait ...
/* Note that this js actually responds
to a click event on the wrapped element!
(not the image) */
$("img.checkable").wrap("<span class='fancychecks'>")
.parent().click(function() {
$(this).toggleClass("checked");
});
/* style the images */
span.fancychecks img {
display: block;
margin: 0;
padding: 0;
transition-duration: 300ms;
transform: scale(1);
filter: none;
-webkit-filter: grayscale(0);
}
span.fancychecks.checked img {
transform: scale(0.8);
filter: gray;
filter: grayscale(1);
-webkit-filter: grayscale(1);
}
/* style the parent spans */
span.fancychecks {
padding: 0;
margin: 5px;
display: inline-block;
border: 1px solid transparent;
transition-duration: 300ms;
}
span.fancychecks.checked {
border-color: #ccc;
}
/* Using conexo's fantastic CSS, make the checkmarks */
span.fancychecks::before {
background-color: rgba(50, 200, 50, 0.7);
color: white;
content: "✓";
font-weight: bold;
border-radius: 50%;
position: absolute;
margin: 2px;
top: 1;
left: 1;
z-index: 1;
width: 25px;
height: 25px;
text-align: center;
line-height: 28px;
transform: scale(0);
transition-duration: 300ms;
}
span.fancychecks.checked::before {
transform: scale(1);
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.0/jquery.min.js"></script>
<img class="checkable" src="http://lorempixel.com/100/100/city/1" />
<img class="checkable" src="http://lorempixel.com/100/100/city/2" />
<img class="checkable" src="http://lorempixel.com/100/100/city/3" />
Inspiré par la solution ci-dessus, j'ai construit un plugin qui peut être utilisé aussi facilement que:
$("img").imgCheckbox();
Voir en action (et voir la source )
J'ajouterais un div supplémentaire avec position: relative;
et class="checked"
qui a la même largeur/hauteur que l'image et la position dans left: 0; top: 0;
contenant l'icône. Cela commence par display: none;
.
Maintenant, vous pouvez écouter l'événement click
-:
$( '.captcha_images' ).click( function() {
$(this + '.checked').css( 'display', 'block' );
$(this).animate( { width: '70%', height: '70%' } );
});
De cette façon, vous pouvez obtenir l'icône et redimensionner l'image en plus petit.
Remarque: je voulais juste vous montrer la "logique" qui se cache derrière mes pensées, cet exemple pourrait ne pas fonctionner ou contenir des bugs.
Voici un exemple rapide de sélection d'une image comme une case à cocher
Exemple mis à jour à l'aide de Knockout.js:
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>
J'ai remarqué que d'autres réponses n'utilisaient pas <label>
(pourquoi pas?) Ou exigeaient des attributs for
et id
correspondants. Cela signifie que si vous avez des identifiants en conflit, votre code ne fonctionnera pas et vous devez vous rappeler de créer des identifiants uniques à chaque fois.
De même, si vous masquez la variable input
avec display:none
ou visibility:hidden
, le navigateur ne se concentrera pas dessus.
Une case à cocher et son texte (ou dans ce cas, une image) peuvent être enveloppés dans une étiquette:
.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>
Pour développer la réponse acceptée par toute personne utilisant WordPress et GravityForms afin de générer leurs formulaires et souhaitant renseigner automatiquement les champs de case à cocher avec une liste de publications et leur Vignette en vedette associée
// 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;
}
Et le 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;
}