Используйте изображения, такие как флажки

146

Я хотел бы иметь альтернативу стандартным флажкам - в основном, я хотел бы использовать изображения и когда пользователь щелкает изображение, исчезает и накладывает галочку.

В сущности, я хочу сделать что-то вроде Recaptcha 2, когда вам нужно щелкнуть изображения, соответствующие определенным критериям. Вы можете увидеть демонстрацию Recaptcha здесь, но иногда это может помочь вам решить текстовые вопросы, в отличие от выбора изображения. Итак, вот скриншот:

Изображение 373

Когда вы нажимаете одно из изображений (в этом случае, содержащее изображение стейка), изображение, которое вы нажимаете, уменьшается по размеру, и появляется синий галочка, указывающий, что вы отметили его.

Скажем, я хочу воспроизвести этот точный пример.

Я понимаю, что у меня может быть 9 скрытых флажков и прикрепить некоторый jQuery, чтобы при щелчке по изображению он выбирает/отменяет скрытый флажок. Но как насчет сокращения изображения/наложения галочки?

  • 2
    Вы можете иметь два одинаковых изображения: одно с галочкой, а другое без галочки. И меняйте изображения по клику
  • 20
    @ Алекс Это было бы особенно негибким решением.
Показать ещё 9 комментариев
Теги:

7 ответов

256
Лучший ответ

Чистое семантическое решение HTML/CSS

Это легко реализовать самостоятельно, без предварительного решения. Также он научит вас многому, поскольку вам не кажется слишком легким использование CSS.

Это то, что вам нужно сделать:

У ваших флажков должны быть разные атрибуты id. Это позволяет подключить к нему <label>, используя метку for -attribute.

Пример:

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

Прикрепление метки к флажку приведет к поведению браузера: всякий раз, когда кто-то нажимает на метку (или изображение внутри нее), этот флажок будет переключен.

Затем вы скроете флажок, применив для него display: none;.

Теперь все, что вам нужно сделать, это установить стиль, который вы хотите для своей метки: перед псевдоэлементом (элементы замены флажка):

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

В последнем сложном шаге вы используете селектор CSS :checked, чтобы изменить изображение, когда установлен флажок:

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

+ (смежный селектор) позволяет вам только заменять метки, которые непосредственно следуют за скрытым флажком в разметке.

Вы можете оптимизировать это, поместив оба изображения в spritemap и применив только изменение background-position вместо замены изображения.

Конечно, вам нужно правильно поместить метку и применить display: block; и установить правильные width и height.

Изменить:

Пример codepen и фрагмент кода, который я создал после этих инструкций, используют ту же технику , но вместо использования изображений для флажков замены флажка выполняются исключительно с помощью CSS, создавая :before на ярлыке, который после проверки имеет content: "✓";. Добавьте округленные границы и сладкие переходы, и результат действительно приятный!

Вот рабочий код, который демонстрирует технику и не требует изображений для флажка:

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

Вот фрагмент кода:

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

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>
  • 30
    Рад, что вам это нравится! Начните возиться с CSS больше, это очень весело, и CSS может сделать намного больше, чем вы, возможно, когда-либо ожидаете (кроме вертикального центрирования, это просто слишком сложно;)).
  • 1
    Да, и понимание того, как это работает, заставит вас думать в будущем, каждый раз, когда вы захотите выполнить какое-нибудь действие DOM. А ты думал, что можешь реагировать только на :hover :)
Показать ещё 19 комментариев
24

Чистое решение для CSS

Вызывается три аккуратных устройства:

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>
  • 0
    Как можно добавить поведение переключателя для этих флажков? Я имею в виду, когда вы нажимаете на изображение, уже выбранное изображение отменяется.
  • 0
    Тот, кто задает себе тот же вопрос, что и @Libertad, просто меняет тип ввода на радио и присваивает им одно и то же имя "attribute" <input type="radio" name="myRadio" id="myRadio1" /> также меняет ваш css на скрыть маркер: input[type=radio]{display: none;}
5

Смотрите этот плагин jQuery: imgCheckbox (на npm и bower)

Отказ от ответственности: Для решения этой проблемы не требуется javascript. Напряженность связана с ремонтопригодностью и эффективностью кода. Хотя нет необходимости в плагине (или любом javascript), он уверен, что он быстрее работает, и часто его легче изменить.

Решение Barebones:

С очень простым HTML (ни один из беспорядков с флажками и ярлыками и т.д.):

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

Вы можете использовать jQuery toggleClass, чтобы включить/выключить класс selected или checked в событии click:

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

Проверяемые элементы выбираются с помощью

$(".checked")

Плюс Coolness:

Вы можете стилизовать изображения, основанные на этом, но большая проблема заключается в том, что без других элементов DOM вы даже не можете использовать ::before и ::after для добавления таких вещей, как отметки. Решение состоит в том, чтобы обернуть ваши изображения другим элементом (и имеет смысл прикрепить прослушиватель кликов к обернутому элементу).

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

Это оставляет ваш html действительно чистым и ваш js невероятно удобочитаемым. Взгляните на фрагмент...

/* 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 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" />

Использование imgCheckbox Плагин jQuery:

Вдохновленный решением выше, я создал плагин, который можно использовать так же легко, как:

$("img").imgCheckbox();
  • Внедряет данные для отмеченных изображений в вашу форму
  • Поддержка пользовательских галочек
  • Поддержка настраиваемых CSS
  • Поддержка предварительно выбранных элементов
  • Поддержка групп радиостанций вместо простого переключения изображений
  • Есть обратные вызовы событий
  • Чувствительные значения по умолчанию
  • Легкий и супер простой в использовании

Смотрите в действиисм. источник)

  • 0
    Мне также нравится этот подход, но у него есть ряд недостатков, о которых стоит упомянуть, самый большой из которых заключается в следующем: если предположить, что пользователь должен выбирать изображения, то информация, предоставленная пользователем таким образом, несомненно, должна как-то обрабатываться, будь то это через вызов AJAX или через форму отправки. Для целей дальнейшей обработки информации, предоставленной пользователем, наличие флажков, в которых должен быть отражен и обработан ряд вариантов, является просто естественным, семантическим способом сделать это.
  • 0
    Это правда, это в моем списке задач для плагина - чтобы захватить отправку формы и вставить данные в форму. Но вы правы, флажки семантические для форм
Показать ещё 3 комментария
5

Я бы добавил дополнительный div с position: relative; и class="checked", который имеет ту же ширину/высоту, что и изображение, а не положение в left: 0; top: 0;, содержащее значок. Он начинается с display: none;.

Теперь вы можете слушать click -event:

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

Таким образом вы можете получить значок, а также изменить размер изображения на меньший путь.

Примечание. Просто хотелось показать вам "логику" моих мыслей, этот пример может не работать или содержать некоторые ошибки.

  • 5
    JS не требуется.
  • 0
    Техника, которую я продемонстрировал, настолько проста и надежна, что даже часто применяется в ситуациях, когда у вас нет семантических флажков, например, переключение отображения других элементов и тому подобное. Это тот случай, когда это не только самое простое и гибкое решение, но и семантически лучшее.
Показать ещё 1 комментарий
2

Вот краткий пример выбора изображения, такого как флажок

Обновленный пример с помощью 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>
  • 1
    Хотя мне нравится ваш подход, большинству было бы полезно заявить, что вы используете Knockout.js в своем примере.
  • 0
    @connexo Cheers, только что обновлен, чтобы сказать пример, используя Knockout.js
0

Чтобы расширить принятый ответ для тех, кто использует WordPress и GravityForms, чтобы сгенерировать их формы и пожелать автоматически заполнить поля флажка списком сообщений и их связанной Featured Thumbnail

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

И 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;
}
0

Я заметил, что другие ответы либо не используют <label> (почему бы и нет?), либо требуют сопоставления атрибутов for и id. Это означает, что если у вас есть конфликтующие идентификаторы, ваш код не будет работать, и вы должны помнить о том, чтобы каждый раз создавать уникальные идентификаторы.

Кроме того, если вы скроете input с помощью display:none или visibility:hidden, браузер не будет фокусироваться на нем.

Флажок и его текст (или в этом случае, изображение) могут быть завернуты в метку:

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

Ещё вопросы

Сообщество Overcoder
Наверх
Меню