Onay kutuları gibi resimler kullanın


165

Standart bir onay kutusuna bir alternatif istiyorum - temel olarak görüntüleri kullanmak istiyorum ve kullanıcı görüntüyü tıkladığında, solmaya ve bir onay kutusunun üzerine yerleşiyor.

Özünde, Recaptcha 2'nin belirli bir kriteri karşılayan resimleri tıklatmanızı sağladığında yaptığı gibi bir şey yapmak istiyorum. Sen edebilirsiniz Demo burada bir reCAPTCHA bkz ancak bazen görüntü seçimi ile değil de, metin soruları çözmeye alabilirsiniz. İşte bir ekran görüntüsü:

Google Recaptcha ekran görüntüsü

Görüntülerden birini tıkladığınızda (bu durumda, biftek resmi içerir), tıkladığınız görüntü küçülür ve işaretlediğinizi belirten mavi onay işareti görünür.

Diyelim ki bu örneği yeniden oluşturmak istiyorum.

9 Gizli onay kutularına sahip olabileceğimi ve görüntüyü tıklattığımda gizli onay kutusunu seçti / seçimini kaldırdığı için bazı jQuery ekleyebileceğimin farkındayım. Peki ya görüntünün daralması / kenenin üst üste binmesi?


2
iki özdeş görüntünüz olabilir: biri kene ve diğeri kene olmadan.
Alex

23
@Alex Bu özellikle esnek olmayan bir çözüm olacaktır.
Siguza

2
Tıklama sırasında resim boyutunu geçersiz kılan :beforeve kene resmi için biraz sihir yapan bir CSS sınıfı eklemeyi / kaldırmayı denediniz mi?
Hexaholic

3
@Alex "Esnek Olmayan", efektin programda yaratılması durumunda durum böyle olmazsa, koleksiyona yeni bir resim eklemek veya "işaretli" simgesini değiştirmek gibi bir şeyi değiştirmek için çok daha fazla çalışma gerektireceği anlamına gelir. Çalışma süresi.
Siguza

2
@Christian Onay kutularını özel bir şeyle değiştirmek, popüler bir tasarım kararıdır (sadece tarz bir onay kutusu olsa bile) ve bunu yapmak için iyi / basit yollar bulmak, onunla uğraşmak zorunda olan geliştiricilerin kesinlikle ilgi çekicidir. Ve bu soru (onay kutusunun değiştirilmesini başka bir şeye yerleştirmek) kesinlikle ilginç bir soru haline getiriyor. Özellikle, görevin belirgin karmaşıklığına rağmen, kabul edilen cevabın hiç JS kullanmadığını not edin
Izkata

Yanıtlar:


309

Saf semantik HTML / CSS çözümü

Bu, kendi başınıza uygulamak kolaydır, önceden yapılmış bir çözüme gerek yoktur. Ayrıca CSS ile çok kolay görünmediğiniz için size çok şey öğretecek.

Yapman gereken bu:

Onay kutularınızın farklı idözelliklere sahip olması gerekir . Bu, etiketin -attribute özelliğini <label>kullanarak a bağlamanızı sağlar for.

Misal:

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

Etiketin onay kutusuna eklenmesi tarayıcı davranışını tetikler: Birisi etiketi (veya içindeki resmi) her tıkladığında onay kutusu açılır.

Ardından, örneğin display: none;üzerine başvurarak onay kutusunu gizlersiniz .

Şimdi tek yapmanız gereken, label::beforesözde öğeniz için istediğiniz stili ayarlamaktır (görsel onay kutusu değiştirme öğeleri olarak kullanılacak):

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

Son zor bir adımda, :checkedonay kutusu işaretlendiğinde görüntüyü değiştirmek için CSS'nin sahte seçicisini kullanırsınız:

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

+( Komşu kardeş seçicisi ) emin yalnızca doğrudan biçimlendirme gizli onay kutusunu takip ettiğini etiketleri değiştirmek yapar.

Her iki görüntüyü bir harita haritasına koyarak background-positionve görüntüyü değiştirmek yerine yalnızca bir değişiklik uygulayarak bunu optimize edebilirsiniz .

Tabii doğru etiketi konumlandırmak ve uygulamak gerekir display: block;ve doğru ayarlamak widthve height.

Düzenle:

Codepen örnek ve ben bu talimatlara sonra oluşturulan hangi pasajı aynı tekniği kullanmak, ancak bunun yerine işaret kutusu görüntüleri kullanmak yerine, onay kutusu değiştirmeler CSS ile tamamen yapılır oluşturarak, ::beforesahip bir kez kontrol, o etikettecontent: "✓"; . Bazı yuvarlak kenarlıklar ve tatlı geçişler ekleyin ve sonuç gerçekten sevimli!

İşte tekniği gösteren ve onay kutusu için resim gerektirmeyen çalışan bir kod kalemi:

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

Parçacıktaki kod aynı:

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>


32
Beğendiğine sevindim! CSS ile daha fazla uğraşmaya başlayın, çok eğlencelidir ve CSS muhtemelen beklediğinizden çok daha fazlasını yapabilir (dikey merkezleme hariç, bu çok zor;)).
connexo

1
Evet, ve nasıl çalıştığını anlamak, her tıklandığında DOM eylemi yapmak istediğinizde düşünmenizi sağlayacaktır. Ve sen sadece tepki verebileceğini düşündün :hover:)
connexo

Bu Pluralsight - bazı CSS şeyler izlemek için bir sonraki şey olacak :)
bgs264

6
Bu çok güzel! Aynı etiketi iki kez tıkladığınızda küçük bir sorun fark ettim, resmi seçer. Bu sorunu
Ayesh K

1
Tick, SVG olarak daha iyi görünecekti. CSS içeriği sizi bazı korkunç sistem fontlarının merhametine sokar.
Adria

31

Saf CSS Çözümü

Çağrılan üç temiz cihaz vardır:

  1. :checkedselektör
  2. ::beforeYalancı seçici
  3. Css contentözelliği.

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>


Bu onay kutularına radyo düğmesi davranışı nasıl eklenebilir? Yani bir görüntüye tıkladığınızda, zaten seçilmiş olan görüntünün seçimi kaldırılır.
Libertad

Kendisine @Libertad ile aynı soruyu soranlar sadece giriş türünü radyoya değiştirir ve onlara aynı adı "özniteliği" verir <input type="radio" name="myRadio" id="myRadio1" />de mermiyi gizlemek için css'nizi değiştirir :input[type=radio]{display: none;}
Lou

8

Şu jQuery eklentisine bakın: imgCheckbox ( npm ve bower üzerinde )

Yasal Uyarı: Bu sorunu çözmek için javascript gerekmez. Gerilim, kodun sürdürülebilirliği ve verimliliği arasındadır. Bir eklentiye (veya herhangi bir javascript'e) ihtiyaç duyulmasa da, daha hızlı oluşturmayı ve genellikle değiştirmeyi daha kolay hale getirir.

Barebones Çözümü:

Çok basit HTML ile (onay kutuları ve etiketlerle karışıklık yok):

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

Olaydaki bir selectedveya checkedsınıfı açmak / kapatmak için jQuery'nin toggleClass öğesini kullanabilirsiniz click:

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

İşaretli öğelerle birlikte getirilir

$(".checked")

Artı Serinlik:

Görüntüleri buna göre şekillendirebilirsiniz, ancak büyük bir sorun, diğer DOM öğeleri olmadan bile kullanamayacağınız ::beforeve ::afteronay işaretleri gibi şeyler ekleyemeyeceğinizdir. Çözüm, görüntülerinizi başka bir öğeyle sarmaktır (ve tıklama dinleyicisini sarılı öğeye de eklemek mantıklıdır).

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

Bu html gerçekten temiz ve js inanılmaz okunabilir bırakır. Snippet'e bir göz atın ...

İmgCheckbox jQuery Eklentisini kullanma :

Yukarıdaki çözümden esinlenerek, aşağıdaki gibi kolayca kullanılabilecek bir eklenti oluşturdum:

$("img").imgCheckbox();
  • İşaretli görüntüler için verileri formunuza enjekte eder
  • Özel onay işaretlerini destekler
  • Özelleştirilmiş CSS'yi destekler
  • Önceden seçilmiş öğeleri destekler
  • Görüntülerin basitçe değiştirilmesi yerine radyo gruplarını destekler
  • Etkinlik geri çağrıları var
  • Mantıklı varsayılanlar
  • Hafif ve süper kolay kullanım

See it eylem (ve kaynağını görmek )


Ben de bu yaklaşımı seviyorum, ama belirtilmesi gereken bazı dezavantajları var, en büyüğü şu: Kullanıcının görüntüleri seçmesi gerektiğini varsayarsak, kullanıcı tarafından bu şekilde verilen bilgiler mutlaka bir şekilde işlenecek, bir AJAX çağrısı veya bir form gönderme yoluyla. Kullanıcı tarafından verilen bilgilerin daha ileri düzeyde işlenmesi için, bir dizi seçeneğin yansıtılması ve işlenmesi gereken onay kutularına sahip olmak, bunu yapmanın doğal, anlamsal yoludur.
connexo

Bu doğru, eklenti için yapılacaklar listemde - form gönderimini kaçırmak ve verileri forma enjekte etmek. Ama haklısın, onay kutuları formlar için
anlamlıdır

Eklentinizi kullanmayı denedim, ancak başlatma işleminden sonra daha fazla resim ekliyorsam, yeni örnekleri dahil edebilmek için önceki örneği yok etmenin bir yolu yok gibi görünüyor
Ian Kim

@IanKim ilginç kullanım örneği, github ile ilgili bir konuda ne yapmaya çalıştığınız hakkında daha fazla bilgi verebilir misiniz? Checkbox
jcuenod

Harika bir eklenti! lütfen bir Webjar yayınlayın =)
naXa

6

İle ekstra bir div eklerdim position: relative; ve class="checked"görüntü vardır ve pozisyon daha da aynı genişlik / yükseklik sahip olan left: 0; top: 0;simge ihtiva etmektedir. İle başlar display: none;.

Şimdi dinleyebilirsiniz click -event :

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

Bu şekilde simgeyi alabilir ve görüntüyü daha küçük bir şekilde yeniden boyutlandırabilirsiniz.

Uyarı: Sadece düşüncelerimin arkasındaki "mantığı" göstermek istedim, bu örnek işe yaramayabilir veya içinde bazı hatalar olabilir.


Gösterdiğim teknik çok basit ve sağlam, semantik olarak herhangi bir onay kutunuzun olmadığı durumlarda bile, diğer öğelerin ve benzerlerinin görüntülenmesini değiştirmek gibi durumlarda bile uygulanır. Bu , yalnızca en kolay, en esnek çözümün değil, aynı zamanda anlamsal olarak en iyi çözümün de olduğu kullanım alanıdır.
connexo

2
Evet haklısın. İlk başta No-JS ve güzel Semantik yolları sevdiğim için ilk cevabınızı işaret etmek ve geliştirmek istedim, ancak OP'nin jQuery'de bir şey istediğini okuduğumdan cevabımı değiştirdim. Nereden aşağı oy aldığımı hatırlıyorum, çünkü OP "daha iyi" veya "doğru" bir çözüm istemiyordu, ama tam olarak yazdığı şekilde. Belki sadece abarttığım veya anlamadığım bir şey var ya da OP'ye bağlı?
Çağatay Ulubay

2

Diğer cevapların ya kullanmadığını <label>(neden olmasın?) Ya da eşleştirme forve idnitelikler gerektirdiğini fark ettim . Bu, çakışan kimlikleriniz varsa, kodunuzun çalışmayacağı ve her seferinde benzersiz kimlikler oluşturmayı hatırlamanız gerektiği anlamına gelir.

Ayrıca, veya inputile gizlerseniz , tarayıcı buna odaklanmaz.display:nonevisibility:hidden

Bir onay kutusu ve metni (veya bu durumda resim) bir etikete sarılabilir:

.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>


1

Burada onay kutusu gibi bir resim seçmenin kısa bir örneği

Knockout.js kullanan Güncellenmiş Örnek:

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>


1
Ben sizin yaklaşımınızı seviyorum, ancak çoğu örnek için Knockout.js kullandığınızı belirtmek için yararlı olacaktır.
connexo

@connexo Cheers, Knockout.js kullanarak örnek söyleyecek şekilde güncellendi
YaBCK

0

Formlarını oluşturmak için WordPress ve GravityForms kullanan herkesin kabul edilen yanıtını genişletmek ve onay kutusu alanlarını otomatik olarak bir gönderi listesi ve ilişkili Öne Çıkan Küçük Resimleri ile doldurmak istiyorsanız

// 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;
}

Ve 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;
}
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.