user10454516
user10454516

Reputation: 1143

Using image for checkbox input

First, please do not mark this as duplicate, cause I want to ask a little modification from this QnA, here. I'm using this answer to achieve what I want, but it almost meets what I need. Here is his demo.

I am trying to achieve what he did, this is what I've made so far. But, when I click the image, because of the border, it makes the images a little get bigger. What I want is, when the image (checkbox) checked, there are checkboxes icon on the top left (its done) and the image surrounds with a border without making the image get bigger. Here is the code in my snippet:

here is the HTML:

<ul>
  <li><input type="checkbox" id="cb1" />
    <label for="cb1"><img src="http://lorempixel.com/103/103" /></label>
  </li>
  <li><input type="checkbox" id="cb2" />
    <label for="cb2"><img src="http://lorempixel.com/102/102" /></label>
  </li>
</ul>

this is the CSS:

ul {
  list-style-type: none;
}    
li {
  display: inline-block;
}    
input[type="checkbox"][id^="cb"] {
  display: none;
}    
label {
  display: block;
  position: relative;
  cursor: pointer;
  width: 100%;
  height: 100%;
}    
label:before {
  background-color: red;
  color: white;
  display: block;
  border: 1px solid red;
  position: absolute;
  width: 20px;
  height: 20px;
  text-align: center;
  line-height: 20px;
  transition-duration: 0.4s;
  -webkit-transition-duration: 0.4s;
  -moz-transition-duration: 0.4s;
  -ms-transition-duration: 0.4s;
}    
label img {
  height: 100%;
  width: 100%;
}    
:checked + label {
  border-color: red;
}    
:checked + label:before {
  content: "✓";
  background-color: red;
  border: 1px solid red;
  z-index: 99;
}    
:checked + label img {
  z-index: -1;
  border: 1px solid red;
}

Thank you!

Upvotes: 0

Views: 3296

Answers (5)

Vương Hữu Thiện
Vương Hữu Thiện

Reputation: 1710

enter image description here

You can use a "label" tag that contains an "img" tag inside.

Here's an example of using an image as a checkbox and radio.

* {
  font-family: Lato;
  margin: 0;
  padding: 0;
  --transition: 0.15s;
  --border-radius: 0.5rem;
  --background: #ffc107;
  --box-shadow: #ffc107;
}

.cont-bg {
  min-height: 100vh;
  background-image: radial-gradient(
    circle farthest-corner at 7.2% 13.6%,
    rgba(37, 249, 245, 1) 0%,
    rgba(8, 70, 218, 1) 90%
  );
  padding: 1rem;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
}

.cont-title {
  color: white;
  font-size: 1.25rem;
  font-weight: 600;
  margin-bottom: 1rem;
}

.cont-main {
  display: flex;
  flex-wrap: wrap;
  align-content: center;
  justify-content: center;
}

.cont-checkbox {
  width: 150px;
  height: 100px;
  border-radius: var(--border-radius);
  box-shadow: 0 0.125rem 0.25rem rgba(0, 0, 0, 0.075);
  background: white;
  transition: transform var(--transition);
}

.cont-checkbox:first-of-type {
  margin-bottom: 0.75rem;
  margin-right: 0.75rem;
}

.cont-checkbox:active {
  transform: scale(0.9);
}

input {
  display: none;
}

input:checked + label {
  opacity: 1;
  box-shadow: 0 0 0 3px var(--background);
}

input:checked + label img {
  -webkit-filter: none; /* Safari 6.0 - 9.0 */
  filter: none;
}

input:checked + label .cover-checkbox {
  opacity: 1;
  transform: scale(1);
}

input:checked + label .cover-checkbox svg {
  stroke-dashoffset: 0;
}

label {
  display: inline-block;
  cursor: pointer;
  border-radius: var(--border-radius);
  overflow: hidden;
  width: 100%;
  height: 100%;
  position: relative;
  opacity: 0.6;
}

label img {
  width: 100%;
  height: 70%;
  object-fit: cover;
  clip-path: polygon(0% 0%, 100% 0, 100% 81%, 50% 100%, 0 81%);
  -webkit-filter: grayscale(100%); /* Safari 6.0 - 9.0 */
  filter: grayscale(100%);
}

label .cover-checkbox {
  position: absolute;
  right: 5px;
  top: 3px;
  z-index: 1;
  width: 20px;
  height: 20px;
  border-radius: 50%;
  background: var(--box-shadow);
  border: 2px solid #fff;
  transition: transform var(--transition),
    opacity calc(var(--transition) * 1.2) linear;
  opacity: 0;
  transform: scale(0);
}

label .cover-checkbox svg {
  width: 13px;
  height: 11px;
  display: inline-block;
  vertical-align: top;
  fill: none;
  margin: 5px 0 0 3px;
  stroke: #fff;
  stroke-width: 2;
  stroke-linecap: round;
  stroke-linejoin: round;
  stroke-dasharray: 16px;
  transition: stroke-dashoffset 0.4s ease var(--transition);
  stroke-dashoffset: 16px;
}

label .info {
  text-align: center;
  margin-top: 0.2rem;
  font-weight: 600;
  font-size: 0.8rem;
}
<div class="cont-bg">
  <div class="cont-title">Checkbox</div>
  <div class="cont-main">
    <div class="cont-checkbox">
      <input type="checkbox" id="myCheckbox-1" />
      <label for="myCheckbox-1">
        <img
          src="https://hips.hearstapps.com/hmg-prod.s3.amazonaws.com/images/2021-mazda-mx-5-miata-mmp-1-1593459650.jpg?crop=0.781xw:0.739xh;0.109xw,0.0968xh&resize=480:*"
        />
        <span class="cover-checkbox">
          <svg viewBox="0 0 12 10">
            <polyline points="1.5 6 4.5 9 10.5 1"></polyline>
          </svg>
        </span>
        <div class="info">Mazda MX-5 Miata</div>
      </label>
    </div>
    <div class="cont-checkbox">
      <input type="checkbox" id="myCheckbox-2" />
      <label for="myCheckbox-2">
        <img
          src="https://hips.hearstapps.com/hmg-prod.s3.amazonaws.com/images/2020-chevrolet-corvette-c8-102-1571146873.jpg?crop=0.548xw:0.411xh;0.255xw,0.321xh&resize=980:*"
        />
        <span class="cover-checkbox">
          <svg viewBox="0 0 12 10">
            <polyline points="1.5 6 4.5 9 10.5 1"></polyline>
          </svg>
        </span>
        <div class="info">Toyota Supra</div>
      </label>
    </div>
  </div>
  <div class="cont-title">Radio</div>
  <div class="cont-main">
    <div class="cont-checkbox">
      <input type="radio" name="myRadio" id="myRadio-1" />
      <label for="myRadio-1">
        <img
          src="https://hips.hearstapps.com/hmg-prod.s3.amazonaws.com/images/2021-mazda-mx-5-miata-mmp-1-1593459650.jpg?crop=0.781xw:0.739xh;0.109xw,0.0968xh&resize=480:*"
        />
        <span class="cover-checkbox">
          <svg viewBox="0 0 12 10">
            <polyline points="1.5 6 4.5 9 10.5 1"></polyline>
          </svg>
        </span>
        <div class="info">Mazda MX-5 Miata</div>
      </label>
    </div>
    <div class="cont-checkbox">
      <input type="radio" name="myRadio" id="myRadio-2" />
      <label for="myRadio-2">
        <img
          src="https://hips.hearstapps.com/hmg-prod.s3.amazonaws.com/images/2020-chevrolet-corvette-c8-102-1571146873.jpg?crop=0.548xw:0.411xh;0.255xw,0.321xh&resize=980:*"
        />
        <span class="cover-checkbox">
          <svg viewBox="0 0 12 10">
            <polyline points="1.5 6 4.5 9 10.5 1"></polyline>
          </svg>
        </span>
        <div class="info">Toyota Supra</div>
      </label>
    </div>
  </div>
</div>

Upvotes: 0

Deepak Sharma
Deepak Sharma

Reputation: 4170

So if requirement is when you click on image, you need to show on left top corner of image, and you also want to show some border around image, then what you have done is absolutely right.

If you are concerned about image moving by n pixel, then keep in mind that border occupy some space unlike outline which doesnt need any space. Outline takes n pixel around object and apply border type effect.

So there are 2 solution -

  1. what @lalji suggested above. when you load page, apply border on image with color as transparent so it will reserve the space for your border and actually you will not see any border around it, and on clicking (selecting image) just change the color of border.

Fiddle for border transparent

label img {
  height: 100%;
  width: 100%;
  border: 1px solid transparent;
}
  1. another will be when you click it, apply the outline instead of border.

Fiddle for outline

:checked + label img {
  z-index: -1;
  outline: 1px solid red;
}
  1. UPADTE if we want to show some image/text also when image selected. if you see here I have added another node saying details that will be shown only when image selected and will be aligned in centre of the image.

Fiddle

This below css rule to hide the details initially and making them in centre etc.

label img + .details
{
  color:white;
  position:absolute;
  top:0px; 
  width:100%;  
  display:none;
  margin-top:50%;
  transform: translatey(-50%);
  text-align:center;
}

Now, we will show the details section if image selected.

:checked + label img + .details
{
  display:block;
}

Upvotes: 0

Partho63
Partho63

Reputation: 3117

Try This:

ul {
  list-style-type: none;
}
li {
  display: inline-block;
}
input[type="checkbox"][id^="cb"] {
  display: none;
}
label {
    border: 1px solid #fff;
  display: block;
  position: relative;
  cursor: pointer;
}
label:before {
  background-color: red;
  color: white;
  content: "";
  display: block;
  border: 1px solid red;
  position: absolute;
  width: 20px;
  height: 20px;
  text-align: center;
  line-height: 20px;
  transition-duration: 0.4s;
  transform: scale(0);
}
label img {
  height: 100%;
  width: 100%;
  transition-duration: 0.2s;
  transform-origin: 50% 50%;
}
:checked + label {
  border-color: red;
}
:checked + label:before {
  content: "✓";
  background-color: red;
  z-index: 99;
  transform: scale(1);
}
:checked + label img {
  z-index: -1;
  transform: scale(0.9);
}
<ul>
  <li><input type="checkbox" id="cb1" />
    <label for="cb1"><img src="http://lorempixel.com/103/103" /></label>
  </li>
  <li><input type="checkbox" id="cb2" />
    <label for="cb2"><img src="http://lorempixel.com/102/102" /></label>
  </li>
</ul>

Upvotes: 0

Xenio Gracias
Xenio Gracias

Reputation: 2758

I gave fixed height and width to li and when the checkbox is checked i am changing the height and width of an image and aligning it in the center. hope this is what you are looking for. thanks.

ul {
  list-style-type: none;
}

li {
  display: inline-block;
}

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

label {
    display: block;
    position: relative;
    cursor: pointer;
    height: 120px;
    border: 1px solid;
    width: 120px;
}

label:before {
  background-color: red;
  color: white;
  display: block;
  position: absolute;
  width: 20px;
  height: 20px;
  text-align: center;
  line-height: 20px;
  transition-duration: 0.4s;
}

label img {
  height: 100%;
  width: 100%;
}

:checked + label {
  border-color: red;
}

:checked + label:before {
  content: "✓";
  background-color: red;
  border: 1px solid red;
  z-index: 99;
}

:checked + label img {
  z-index: -1;
    position: absolute;
    top: 50%;
    left: 50%;
    transform: translate(-50%, -50%);
    height: 100px;
    width: 100px;
}
<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>

Upvotes: 0

Lalji Tadhani
Lalji Tadhani

Reputation: 14159

Add Border for img with transparent

label img {
  height: 100%;
  width: 100%;
  border: 1px solid transparent;
}

https://codepen.io/anon/pen/PVRxRM

Upvotes: 1

Related Questions