2

I use splidejs to create a slider for image and text content. The size of the sliderList (ul) is based on the largest list item (sliderItem --> li). Each SliderItem consists of a wrapper (item-wrapper), which contains an image and a text. Both the image and the text can be of different length/highness. Now the SliderItems should be aligned so that each image element is above the text, but the texts are aligned at the bottom of the container (with a dynamic height) and each text starts at the same height. That is, the texts are all placed at the same height at the end of the container and the image should be placed directly above them with a defined margin. Is this somehow possible using SCSS? In case of need I can also use JS to reposition something if needed.

Attached is a mockup of how it should look: enter image description here

Some code snippet: HTML

<div class="splide">
  <div class="splide__track">
    <ul class="splide__list"> //Slider List
       <li class="splide__slide"> //Slider Item
        <div class="item-wrapper"> 
         <div class="image">
           <img/>
         </div>
        <div class="text">
         <h2>Some text</h2>
          Some other text
        </div>
       </div>
      </li>

CSS

  .splide {
       width:100%;
       height: 100%;
     }
     .splide__list {
       display: flex;
       .splide__slide{
          .item-wrapper{
             display: flex;
             flex-direction: column;
             justify-content: space-between;
             height: 100%;
             width: 100%;
              .image {
                img {
                  width: 100%
                  height: auto
                }
              }
              .text {
              }
            }
          }
        }
Alex
  • 132
  • 1
  • 4
  • 21

4 Answers4

0

If you wanted to solve this placement with CSS then it has grid written all over it. Here's an example of what that solution would look like retaining your HTML structure.

ul {
  display: grid;
  grid-template-rows: 1fr 1fr;
  grid-auto-flow: column;
  grid-auto-columns: 1fr;
  list-style: none;
  margin: 0;
  padding: 0;
}

.splide__slide,
.item-wrapper {
  display: contents;
}

.image {
  display: flex;
  align-items: flex-end;
}

https://jsfiddle.net/yd0or3je/

Notice that the li and .item-wrapper had to be eliminated from the layout using display: contents and unless that slider js thingy is only manipulating the ul scroll position or something, it will probably no longer work after these changes.

Other than that you could use javascript to find the highest .image after the page loads and then apply the same height to all the .image elements.

Or the third option would be to just not use the slider js thingy and write some custom js for the slider while retaining the grid css for the layout.

Hope this helps you.

Tanel Eero
  • 642
  • 3
  • 8
0

Your code snippet seems to have lost some material somewhere. However, if I have worked it out correctly, then the code example below I think satisfies the following requirements:

  • maintains your HTML structure (so it should still work with your slider?)
  • aligns the boundaries between images and text
  • does not require javascript

The approach in the code below is to create a reference line for each image and text pairing which can also be referenced to an outer container. This is done by decoupling the layout flow for the image and the text from its parent using 'position'. Decoupling both elements from their shared parent results in the parent collapsing to an element with 0 height, ie, a "line", because it no longer has any layout content. This "line" can then be referenced back a common ancestor, for all image text pairs, again using 'position'.

.splide {
    width:100%;
    height: 100%;
}

.splide__list {
    list-style-type: none;
    display: flex;
    flex-direction: row;

    /*  Establish common reference context  */
    position: absolute;
    top: 50%;
}

.splide__slide {

}

.item-wrapper {

    margin-left: 5px;
    margin-right: 5px;
    width: 20vw;

    /*  Establish image text pairing parent position reference  */
    position: relative;
}

.image {
    border: 2px solid black;  /*  If the black border is not required, then remove this property  */
    padding: 5px;

    /*  Align the bottom of the image, and center the image  */
    position: absolute;
    bottom: 5px;
    left: 5px;
    right: 5px;
}

img {
    width: 100%;
}

.text {
    border: 2px solid black;  /*  If the black border is not required, then remove this property  */
    padding: 5px;

    /*  Align the top of the text, and center the text  */
    position: absolute;
    top: 5px;
    left: 5px;
    right: 5px;
}

.upperGreenBorder {  /*  If the lime border is not required, then remove this class  */
    border-left: 2px solid lime;
    border-top: 2px solid lime;
    border-right: 2px solid lime;
    position: absolute;
    top: -7px;
    bottom: -7px;
    left: -7px;
    right: -7px;
}

.lowerGreenBorder {  /*  If the lime border is not required, then remove this class  */
    border-left: 2px solid lime;
    border-bottom: 2px solid lime;
    border-right: 2px solid lime;
    position: absolute;
    top: -7px;
    bottom: -7px;
    left: -7px;
    right: -7px;
}
<div class="splide">
    <div class="splide__track">
        <ul class="splide__list">
            <li class="splide__slide">
                <div class="item-wrapper"> 
                    <div class="image">
                        <div class="upperGreenBorder"></div><!-- If the lime border is not required, then remove this div -->
                        <img height="400px" src="https://dummyimage.com/1400x600/ff4400/fff.png&text=1">
                    </div>
                    <div class="text">
                        <div class="lowerGreenBorder"></div><!-- If the lime border is not required, then remove this div -->
                        <h2>Some header text 1</h2>
                        <p>Some other text for text number one Some other text for text number one Some other text for text number one</p>
                        <p>Some other text for text number one</p>
                        <p>Some other text for text number one</p>
                        <p>Some other text for text number one</p>
                        <p>Some other text for text number one</p>
                        <p>Some other text for text number one</p>
                        <p>Some other text for text number one</p>
                        <p>Some other text for text number one</p>
                        <p>Some other text for text number one</p>
                    </div>
                </div>
            </li>
            <li class="splide__slide">
                <div class="item-wrapper"> 
                    <div class="image">
                        <div class="upperGreenBorder"></div><!-- If the lime border is not required, then remove this div -->
                        <img height="500px" src="https://dummyimage.com/1400x600/ff4400/fff.png&text=2">
                    </div>
                    <div class="text">
                        <div class="lowerGreenBorder"></div><!-- If the lime border is not required, then remove this div -->
                        <h2>Some header text 2</h2>
                        <p>Some other text for text number two Some other text for text number two Some other text for text number two</p>
                        <p>Some other text for text number two</p>
                    </div>
                </div>
            </li>
            <li class="splide__slide">
                <div class="item-wrapper"> 
                    <div class="image">
                        <div class="upperGreenBorder"></div><!-- If the lime border is not required, then remove this div -->
                        <img height="200px" src="https://dummyimage.com/1400x600/ff4400/fff.png&text=3">
                    </div>
                    <div class="text">
                        <div class="lowerGreenBorder"></div><!-- If the lime border is not required, then remove this div -->
                        <h2>Some header text 3</h2>
                        <p>Some other text for text number three</p>
                        <p>Some other text for text number three</p>
                        <p>Some other text for text number three</p>
                        <p>Some other text for text number three</p>
                        <p>Some other text for text number three</p>
                        <p>Some other text for text number three</p>
                        <p>Some other text for text number three</p>
                        <p>Some other text for text number three</p>
                        <p>Some other text for text number three</p>
                    </div>
                </div>
            </li>
            <li class="splide__slide">
                <div class="item-wrapper"> 
                    <div class="image">
                        <div class="upperGreenBorder"></div><!-- If the lime border is not required, then remove this div -->
                        <img height="300px" src="https://dummyimage.com/1400x600/ff4400/fff.png&text=4">
                    </div>
                    <div class="text">
                        <div class="lowerGreenBorder"></div><!-- If the lime border is not required, then remove this div -->
                        <h2>Some header text 4</h2>
                        <p>Some other text for text number four</p>
                        <p>Some other text for text number four</p>
                        <p>Some other text for text number four</p>
                        <p>Some other text for text number four</p>
                    </div>
                </div>
            </li>
            <li class="splide__slide">
                <div class="item-wrapper"> 
                    <div class="image">
                        <div class="upperGreenBorder"></div><!-- If the lime border is not required, then remove this div -->
                        <img height="400px" src="https://dummyimage.com/1400x600/ff4400/fff.png&text=5">
                    </div>
                    <div class="text">
                        <div class="lowerGreenBorder"></div><!-- If the lime border is not required, then remove this div -->
                        <h2>Some header text 5</h2>
                        <p>Some other text for text number five</p>
                        <p>Some other text for text number five</p>
                        <p>Some other text for text number five</p>
                        <p>Some other text for text number five</p>
                        <p>Some other text for text number five</p>
                        <p>Some other text for text number five</p>
                        <p>Some other text for text number five</p>
                        <p>Some other text for text number five</p>
                        <p>Some other text for text number five</p>
                        <p>Some other text for text number five</p>
                        <p>Some other text for text number five</p>
                        <p>Some other text for text number five</p>
                        <p>Some other text for text number five</p>
                    </div>
                </div>
            </li>
            <li class="splide__slide">
                <div class="item-wrapper"> 
                    <div class="image">
                        <div class="upperGreenBorder"></div><!-- If the lime border is not required, then remove this div -->
                        <img height="50px" src="https://dummyimage.com/1400x600/ff4400/fff.png&text=6">
                    </div>
                    <div class="text">
                        <div class="lowerGreenBorder"></div><!-- If the lime border is not required, then remove this div -->
                        <h2>Some header text 6</h2>
                        <p>Some other text for text number six</p>
                    </div>
                </div>
            </li>
        </ul>
    </div>
petern0691
  • 868
  • 4
  • 11
0

You should set the height of all your splide elements to 100%. Inside your splide__slide, set the .image CSS class into height: 60% and .text class height: 40%, or whichever proportion you prefer. Then, turn the .image CSS class into a flex container and set the img element to be align-self: end. I tried matching your HTML and CSS. Here's a working version with imports for SplideJS:

https://jsfiddle.net/opLsgf9v/

  • What happens when there is more text than image, eg, the height ratio needs to be 40:60 rather than 60:40 for some slider items? – petern0691 Oct 04 '22 at 22:36
  • @Petern Height ratio should be determined manually depending on text and image sizes. As in the mockup provided, ratio might be 70% image to 30% text. This should be decided by OP. – santidiazg Oct 05 '22 at 19:17
  • That would make a slider with dynamic content a bit difficult? – petern0691 Oct 05 '22 at 22:56
-1

Thanks for all your answers. I made it work by some hacky js: First i need to wait for my document to be fully loaded calling

 document.addEventListener('readystatechange', () => {
  if (document.readyState === 'complete') {
    this.calculateImages();
  }
});

then i process every image and calculcate the tallest image (get the height of the tallest element in pixels). After this, i move every image by its height difference (difference actuall image to max height image) by applying the height difference with a margin-top. Thats it for me. I guess a bit hacky but it works.

Alex
  • 132
  • 1
  • 4
  • 21