Search code examples
htmlcsscss-shapeslinear-gradients

How to construct a triangle of required size from linear gradient?


I managed to remove the default arrow image for select element, using webkit-appearance, as I run this in chrome.

I am new to css, I got this idea constructing triangle from this codepen, I want to construct triangle of required size, as you see from snippet triangle is not neatly shaped.

I have some question on this,

  1. In the background-position 100% refers to select element width. Is this correct?
  2. What does these calculation calc(100% - 2.5em) 0.5em mean for background-position ?
  3. For background-size 20px 10px means from horizontally 20px and from top 10 px, am I correct?
  4. If yes making 0px 0px makes this entire image disappear from screen, 0 px takes reference from where in the screen?

select {
     width:150px;
     height:50px;
      -webkit-appearance: none; 
       background-image: 
           linear-gradient(45deg,transparent 50% , black 50% ),
           linear-gradient(135deg, black 50%, transparent 50%);

       background-position:
          calc(100% - 20px) calc(100% - 20px),
          calc(100% - 15px) calc(100% - 20px),
          calc(100% - 2.5em) 0.5em;
      background-size:
          20px 10px,
          10px 10px,
          5px 1px;
      background-repeat: no-repeat;
    }
<select class="version">
        <option value="1">1</option>
        <option value="2">2</option>
        <option value="3">3</option>
        <option value="4"> 4</option>
        <option value="5">5</option>
    </select>


Solution

  • You will find the answers to all your questions here: Using percentage values with background-position on a linear gradient

    In the other hand, you can optimize the code like below to have better control over the triangle:

    select {
         width:150px;
         height:50px;
          -webkit-appearance: none; 
           background-image: 
               linear-gradient(to top left ,transparent 50%, black 0),
               linear-gradient(to top right,transparent 50%, black 0);
           background-position:
           /* The same top value for both 
              The right of the second one is the first + the width*/
              top 15px right 5px,
              top 15px right 15px;
          background-size:
            /*width height. both will have the same so the final result will be 2*Width Height*/
              10px    10px; 
          background-repeat: no-repeat;
        }
    <select class="version">
            <option value="1">1</option>
            <option value="2">2</option>
            <option value="3">3</option>
            <option value="4"> 4</option>
            <option value="5">5</option>
        </select>

    With CSS variables you can make it easier:

    select {
         --t:15px;  /* offset from top */
         --r:5px;   /* offset from right*/
         --w:20px; /* Overal width*/
         --h:10px; /* Overal height*/
      
         width:150px;
         height:50px;
          -webkit-appearance: none; 
           background-image: 
               linear-gradient(to top left ,transparent 50%, black 0),
               linear-gradient(to top right,transparent 50%, black 0);
           background-position:
           /* The same top value for both 
              The right of the second one is the first + the width*/
              top var(--t) right var(--r),
              top var(--t) right calc(var(--r) + var(--w)/2);
          background-size:
            /*width height. both will have the same so the final result will be 2*Width Height*/
              calc(var(--w)/2) var(--h); 
          background-repeat: no-repeat;
        }
    <select class="version">
            <option value="1">1</option>
            <option value="2">2</option>
            <option value="3">3</option>
            <option value="4"> 4</option>
            <option value="5">5</option>
        </select>
        
        <select class="version" style="--w:10px;--r:10px;--t:10px">
            <option value="1">1</option>
            <option value="2">2</option>
            <option value="3">3</option>
            <option value="4"> 4</option>
            <option value="5">5</option>
        </select>
        
           <select class="version" style="--w:30px;--h:20px;--t:10px">
            <option value="1">1</option>
            <option value="2">2</option>
            <option value="3">3</option>
            <option value="4"> 4</option>
            <option value="5">5</option>
        </select>

    also Related: https://stackoverflow.com/a/49696143/8620333