Search code examples
htmlrazor

html create "checkbox-like" layout without checkmark (razor)


I am trying to create this layout:

enter image description here

the user can select one or multiple items from this list:

enter image description here

<table class="itemBackgrond centered" id="@elem.CategoryId"> @*give it id as cat name*@
    <tr>
        <td>
            <p>
                @elem.Title
            </p>
            <input style="display: none;" type="text" value="" name="selectedIdentifier"  class="@elem.CategoryId" /> @
        </td>
    </tr>
    <tr>
        <td>
            <img class="imgSmall" src="@elem.ImageSource" />
        </td>
    </tr>
</table>

I achieved this working with my own logic and creating my own layouts for everything, but I would much rather have those be checkboxes that just look a little different.

They dont have a checkmark, and if they are checked they change the background color. Also I need text and images inside the checkbox.

I was wondering if this is even achievable, or if I should maybe go another way.

What is your recomendation to create a list with items like this and multiple choice but not creating a whole own logic but rather stick to framework material?

thank you


Solution

  • As already stated in the comment, this is a Frontend issue and should be solved in the Frontend not with C#, respectively Razor.

    non-JS Solution

    You can solve this with pure HTML and CSS which Markupwise is not correct and overall not the cleanest solution (also not necessarily the most accessible one). However, you would not require JS for it.

    input[type="checkbox"] {
      display: none;
    }
    
    label {
      display: inline-flex;
      justify-content: center;
      align-items: center;
      border-radius: 1em;
      height: 10em;
      width: 10em;
      background-color: aquamarine;
    }
    
    input[type="checkbox"]:checked + label {
      background-color: skyblue;
    }
    <input type="checkbox" id="BauUndHandwerk">
    <label for="BauUndHandwerk">Bau und Handwerk</label>
    
    <input type="checkbox" id="BeratungUndCoaching">
    <label for="BeratungUndCoaching">Beratung & Coaching</label>
    
    <input type="checkbox" id="EinkaufUndVertrieb">
    <label for="EinkaufUndVertrieb">Einkauf & Vertrieb</label>
    
    <input type="checkbox" id="Einzelhandel">
    <label for="Einzelhandel">Einzelhandel</label>

    This works because you hide the checkbox in CSS by using display: none in the CSS. Then the cards themself are the labels connected to the input. In CSS you can use the + combinator to change the label color when the checkbox is checked.

    JS Solution

    The JS solution is cleaner. It basically works by adding an eventListener to the cards and toggling a CSS class.

    const ELEMENTS = document.querySelectorAll('div');
    
    ELEMENTS.forEach(element => 
      element.addEventListener('click', function(e) {
        e.target.classList.toggle('checked');
      })
    );
    div {
      display: inline-flex;
      justify-content: center;
      align-items: center;
      border-radius: 1em;
      background-color: aquamarine;
      height: 10em;
      width: 10em;
    }
    
    .checked {
      background-color: skyblue;
    }
    <div>Bau und Handwerk</div>
    <div>Beratung & Coaching</div>
    <div>Einkauf & Vertrieb</div>
    <div>Einzelhandel</div>

    You select all elements with document.querySelectorAll() which will return a Node List. Then you iterate over the Node List with forEach and add an eventListener to it. Then you can use the event delegation to toggle a class with classList.toggle()