チェックボックスのような画像を使用する


164

標準のチェックボックスの代わりにしたいのですが、基本的には画像を使用し、ユーザーが画像をクリックするとフェードアウトしてチェックボックスをオーバーレイします。

本質的には、Recaptcha 2のように、特定の基準を満たす画像をクリックするようにしたいのですが。ここでRecaptchaのデモ見ることができますが、画像の選択とは対照的に、テキストの質問を解決できる場合があります。これがスクリーンショットです。

Google Recaptchaスクリーンショット

いずれかの画像(この場合は、ステーキの写真が含まれています)をクリックすると、クリックした画像のサイズが縮小され、青いチェックマークが表示され、チェックしたことを示します。

この正確な例を再現したいとしましょう。

私は9つの非表示のチェックボックスを持つことができることに気付き、画像をクリックすると非表示のチェックボックスが選択または選択解除されるようにjQueryをいくつかアタッチします。しかし、画像の縮小/目盛りのオーバーレイについてはどうですか?


2
2つの同一の画像を使用できます。1つには目盛りがあり、もう1つには目盛りがありません。クリックで画像を変更
Alex

22
@アレックスそれは特に柔軟性のないソリューションでしょう。
Siguza

2
画像サイズをオーバーライド:beforeし、ティック画像に魔法をかけるクリックでCSSクラスを追加/削除してみましたか?
ヘキサホリック

3
@Alex "柔軟性のない"という意味では、コレクションに新しい画像を追加したり、「チェックマーク」アイコンを変更したりするなど、何かを変更するにはさらに多くの作業が必要になります。ランタイム。
Siguza

2
@Christianチェックボックスをカスタムのもので置き換えることは、一般的な設計上の決定です(たとえスタイル付きチェックボックスであっても)、それを行うための良い/簡単な方法を見つけることは、それに対処しなければならなかった開発者にとって間違いなく興味があります。そして、この質問(チェックボックスの置き換えを他のものの上に重ねる)は間違いなく興味深い質問です。具体的には、受け入れられた答えは、タスクの見かけ上の複雑さにもかかわらず、全くJSを使用しない方法に注意してください
Izkata

回答:


308

純粋なセマンティックHTML / CSSソリューション

これは自分で実装するのが簡単で、既成のソリューションは必要ありません。また、CSSは簡単すぎるとは思えないため、多くのことを学ぶことができます。

これはあなたがする必要があることです:

チェックボックスには異なるid属性が必要です。これにより<label>、ラベルの- for属性を使用して、に接続できます。

例:

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

チェックボックスにラベルを付けると、ブラウザの動作がトリガーされます。誰かがラベル(またはラベル内の画像)をクリックすると、チェックボックスが切り替わります。

次に、たとえばチェックボックスを適用することにより、チェックボックスを非表示にしますdisplay: none;

あとは、label::before疑似要素に必要なスタイルを設定するだけです(これは、視覚的なチェックボックスの置換要素として使用されます)。

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

最後のトリッキーなステップでは、CSSの:checked疑似セレクターを使用して、チェックボックスがオンのときに画像を変更します。

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

+隣接兄弟セレクタ)あなたが唯一の直接マークアップに隠されたチェックボックスに従ってラベルを変更できます。

これを最適化するには、両方の画像をスプライトマップに入れ、画像background-positionを交換する代わりに変更のみを適用します。

もちろん、ラベルを正しく配置し、正しく適用display: block;して設定する必要がwidthありheightます。

編集:

これらの手順の後に作成したコードペンの例とスニペットは同じ手法を使用していますが、チェックボックスに画像を使用する代わりに、チェックボックスの置換は純粋に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;
  -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
あなたがそれを気に入ってうれしい!CSSをいじくり回し始めると、それはたくさんの楽しみであり、CSSはおそらく想像以上に多くのことを実行できます(垂直方向のセンタリングを除いて、それは非常に難しいです;))。
connexo

1
ええ、そして、それがどのように動作するかを理解することは、あなたがクリックでDOMアクションをしたいときはいつでも、あなたは将来を考えるようになります。そして、あなただけに反応できると思った:hover:)
connexo

それはPluralsightで見る次の私の物です-いくつかのCSSもの:)
bgs264

6
これはすごく素敵!同じラベルを2回クリックすると、画像が選択されるという小さな問題に気づきました。これにより修正されます:codepen.io/anon/pen/jPmNjg
Ayesh K

1
TickはSVGとして見栄えが良かったでしょう。CSSコンテンツは、いくつかのひどいシステムフォントのなすがままになります。
アドリア2015

31

純粋なCSSソリューション

呼び出される3つのきちんとしたデバイスがあります。

  1. :checkedセレクタ
  2. ::before擬似セレクタ
  3. css contentプロパティ。

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>


これらのチェックボックスにラジオボタンの動作を追加するにはどうすればよいですか?つまり、画像をクリックすると、すでに選択されている画像の選択が解除されます。
Libertad

@Libertadはちょうどラジオへの入力の種類を変更し、それらをすべて同じ名前「属性」を与えるとして誰でも自分自身に同じ質問をして<input type="radio" name="myRadio" id="myRadio1" />弾丸を隠すためにも、あなたのCSSを変更:input[type=radio]{display: none;}
ルー

8

このjQueryプラグインを参照してください:imgCheckbox(上のNPM

免責事項:この問題を解決するためにJavaScriptは必要ありません。緊張は、保守性とコードの効率の間にあります。プラグイン(または任意のJavaScript)は必要ありませんが、ビルドが速くなり、多くの場合変更が容易になります。

ベアボーンソリューション:

非常にシンプルなHTML(チェックボックスやラベルなどの混乱がない):

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

jQueryのtoggleClassを使用して、イベントでselectedまたはcheckedクラスをオン/オフにすることができますclick

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

チェックされたアイテムは、

$(".checked")

さらにクールさ:

これに基づいて画像のスタイルを設定できますが、大きな問題は、他のDOM要素がない::beforeと使用できず::after、チェックマークなどを追加できないことです。解決策は、画像を別の要素でラップすることです(ラップされた要素にもクリックリスナーをアタッチすることは理にかなっています)。

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

これにより、HTMLは本当にクリーンになり、JSは非常に読みやすくなります。スニペットを見てください...

imgCheckboxの使用 jQueryプラグインの:

上記のソリューションに触発されて、私は次のように簡単に使用できるプラグインを作成しました。

$("img").imgCheckbox();
  • チェックした画像のデータをフォームに挿入します
  • カスタムチェックマークをサポート
  • カスタマイズされたCSSをサポート
  • 事前選択された要素をサポート
  • 画像の単純な切り替えの代わりに無線グループをサポート
  • イベントコールバックがある
  • 実用的なデフォルト
  • 軽量で超使いやすい

実際見る(そしてソース見る


私もこのアプローチが好きですが、言及する価値のある欠点がいくつかあります。最大のものはこれです。ユーザーが画像を選択することを想定している場合、ユーザーがこのようにして提供した情報は確かに何らかの形で処理されることを意図しています。 AJAX呼び出しまたはフォーム送信を介して。ユーザーが指定した情報をさらに処理する目的で、多数の選択肢を反映して処理する必要があるチェックボックスを用意することは、それを行うための自然で意味的な方法です。
connexo 2015年

これは本当です、それはプラグインの私のtodoリストにあります-フォーム送信をハイジャックし、データをフォームに注入することです。しかし、そうです、チェックボックスはフォームのセマンティックです
jcuenod

プラグインを使用してみましたが、初期化後にさらに画像を追加する場合、前のインスタンスを破棄して新しい画像を含めることができないようです
Ian Kim

@IanKimの興味深いユースケース、githubの問題で何をしようとしているのかについて詳しく説明できますか?github.com/jcuenod/imgCheckbox
jcuenod

それは素晴らしいプラグインです!Webjarを公開してください=)
naXa 2018年

6

私は、余分な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%' } );
});

このようにして、アイコンを取得し、画像のサイズを小さくすることができます。

通知:私の考えの背後にある「ロジック」を表示したかっただけで、この例は機能しないか、いくつかのバグがある可能性があります。


私が示した手法は非常にシンプルで堅牢であり、他の要素の表示を切り替えるなど、意味的にチェックボックスがない状況でもしばしば適用されます。これは、最も簡単で柔軟なソリューションであるだけでなく、意味的にも最適なユースケースです。
connexo

2
はい、あなたが正しい。最初は私がNo-JSとセマンティックな方法が好きなので、最初の答えを指摘して(編集する前に)改善したかったのですが、OPがjQueryで何かを求めているので、答えを変更しました。OPは「より良い」または「正しい方法」のソリューションではなく、彼が書いた正確な方法を望んでいないので、どこで反対票を獲得したかを覚えています。たぶん私が読んだもの、あるいは理解しなかったものがあるのでしょうか、それともOPに依存しているのでしょうか?
Cagatay Ulubay

2

他の回答が使用しない<label>(なぜ使用しないのか)か、一致forid属性が必要なことに気づきました。つまり、IDが競合している場合、コードは機能せず、毎回一意の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>


1

チェックボックスのような画像を選択する簡単な例を示します

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を使用していることを述べることはほとんどの人にとって役立つでしょう。
connexo 2015年

@connexo Cheers、Knockout.jsを使用した例を示すように更新
YaBCK

0

WordPressとGravityFormsを使用してフォームを生成し、チェックボックスフィールドに投稿のリストと関連する注目サムネイルを自動的に入力したい場合に、受け入れられた回答を拡張する

// 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;
}
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.