CSS & JS Problem. Responsive DIV Container

I don’t have a Kirby problem. But my css and javascript skills are not good enough to solve this problem.

I want to use the Leafleat library to display a map. The prerequisite for using this library is a DIV container with a fixed height. But I want to use a responsive design. The DIV container has a max-width: 35rem. The height should always correspond to the width. So I need to dynamically change the height of the DIV container. How can I do that?

Martin

I don’t think this is necessary. Just set height:100%, provided your parent container has a height set to it.

Hi Sonja,

thanks for your replay!

If I set the height of the leaflet DIV (id=“map”) to 100%, the DIV has a height of 0px and is not displayed.
If I also add a DIV as a parent (class="kirby-leaflet-map) to the leaflet DIV (id=“map”), I also have to specify the height there. But then only the width changes. The height remains the same constant. But I would like it if the height changes according to the width, as is the case with pictures.

<div class="kirby-leafleat-map">
    <div id="map" style="height: 100%; width:100%;"></div>
</div>

and css

.kirby-leafleat-map{
  height: 20rem; 
  max-width:35rem;
}

I use the leaflet library in a Plugin. And this is the content of site/plugins/gpx-leaflet/snippet/blocks/gpxtrackleaflet.php

<?php if($block->gpxtrack()->isNotEmpty()): ?>
    <div class="kirby-leafleat-map">
        <div id="map" style="height: 100%; width:100%;"></div>
    </div>
    <script>
        if (map != undefined) { map.remove(); } 
        var map = L.map('map').setView([51.505, -0.09], 13);

        var tiles = L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
            maxZoom: 19,
            attribution: '&copy; <a href="http://www.openstreetmap.org/copyright">OpenStreetMap</a>'
        }).addTo(map);

        var gpx = '<?= $block->gpxtrack()->toFile()->url() ?>'; // URL to your GPX file or the GPX itself
        new L.GPX(gpx, {
            async: true,
            marker_options: {
                startIconUrl: '/assets/js/leaflet-gpx/pin-icon-start.png',
                endIconUrl: '/assets/js/leaflet-gpx/pin-icon-end.png',
                shadowUrl: '/assets/js/leaflet-gpx/pin-shadow.png'
            }
        }).on('loaded', function(e) {
        map.fitBounds(e.target.getBounds());
        }).addTo(map);
    </script>    
    
<?php endif; ?>

Martin

Hi there,
first of all I think you have to set the outer container to position: relative so the child-container (#map) gets the right height.

But if you really want to keep the aspect-ratio of your map, you either have to work with grid or the old responsive iframe hack for videos. With that you need an extra container to set the width of your map and the height is defined with top or bottom padding. the actual map is inserted with an absolute position.

The code would be something like this:

<div class="wrapper">
  <div class="kirby-leafleat-map">
      <div id="map"></div>
  </div>
</div>

And the CSS:

.wrapper {
  width: 100%;
  max-width: 35rem;
  position: relative;
}

.kirby-leafleat-map {
  width: 100%;
  height: 0;
  padding-bottom: 56.25%; /* this gives you a 16/9 ratio**/
  position: relative;
}

#map {width: 100%;
  height: 100%;
  position: absolute;
  left: 0;
  top: 0;
}

You can see it here how it works

Cheers
tom

Great Tom,

thanks - it works!

But I still don’t understand why it works like this. That’s a lesson to learn - my skills with css can be improved :slight_smile:

Martin

Glad it helped you out. And yeah I know this is kinda weird, baut as far as I know the padding is the only percentage value thats always calculated from width of a container. So if the container has width of 100% you can create aspect ratios with the top or bottom padding, 100% padding creates a square. This changes now with the grid-layout, but a few years ago this was the only solution.

So happy coding
tom

If sass is your thing, i have a function / mixin setup for this kind of stuff, and works maps too. Just alter the first line for different ratios if you need to.

$ioe-padding: ((100 / 16) * 9);

@function to-percentage($input) {
    @return $input * 1%;
}

@mixin ioe {
  height: 0;
  padding-bottom: to-percentage($ioe-padding);
  position: relative;

  canvas,
  embed,
  iframe,
  object,
  video {
    border: 0;
    height: 100%;
    left: 0;
    position: absolute;
    top: 0;
    user-select: none;
    width: 100%;
  }
}

.embed {
 @include ioe;
}

HTML

<div class="embed">
 <!-- iframe/ video / canvas tag etc -->
</div>