Dogfalo / materialize

Materialize, a CSS Framework based on Material Design
https://materializecss.com
MIT License
38.86k stars 4.74k forks source link

Swipeable tabs showing half-page width #4148

Open CiccaGuru opened 7 years ago

CiccaGuru commented 7 years ago

Description

On my website I had some tabs in header. I just added {swipeable:true} to the tab init function, but now the tab divs are displayed not in full width.

mchalakov commented 7 years ago

I found this in materialize.css to be causing the problem: .carousel .carousel-item { display: none; width: 200px; height: 200px; position: absolute; top: 0; left: 0; }

CiccaGuru commented 7 years ago

I just changed that width value you suggested to "100%" and it's now working. Haven't figured out how to correct the height value, though

mchalakov commented 7 years ago

Exactly the same problem here. Tried it also ,the height is the problem now.

CiccaGuru commented 7 years ago

I managed to do like that: .tabs-content.carousel { height: 100%; overflow-x:hidden; overflow-y: scroll; } .tabs-content.carousel .carousel-item { width: 100%; height: 100%; } html,body{ overflow:hidden; height:100%; }

triskill commented 7 years ago

my solution for swipeable tabs in modal (jQuery):

$('.modal').modal({
    ready : function(modal, trigger){
        // initialize tabs
        $('ul.tabs').tabs({
            swipeable : true
        });
        // remove materialize default 200px and 400px carousel height
        var modalH = pixelsToNumber($(modal).css('height'));
        var swipeH = pixelsToNumber($(modal).find('.tabs').css('height'));
        var footerH = pixelsToNumber($(modal).find('.modal-footer').css('height'));
        var carouselHeight = modalH -swipeH -footerH;
        $('.modal .carousel').css('height', carouselHeight+'px');
        $('.modal .carousel').css('overflow-y', 'auto');
    }
});
var pixelsToNumber = function(pixels){
    return Number(pixels.substring(0,pixels.length-2));
};
donacross commented 7 years ago

Demo

Bug

image

Expected behavior

image

DanielRuf commented 7 years ago

@donacross use the right markup and do not forget the wrappers https://codepen.io/anon/pen/KqapbE?editors=1000

http://materializecss.com/tabs.html#structure

Badlapje commented 7 years ago

that codepen shows the exact same problem as described by @donacross ... how is that a fix?

Badlapje commented 7 years ago

if one replaces the content of the offical docs with something that has a big height it also get's truncated btw

DanielRuf commented 7 years ago

that codepen shows the exact same problem as described by @donacross ... how is that a fix?

What exactly do you mean? He used the wrong markup. The codepen that I gave shows the expected behavior.

Badlapje commented 7 years ago

in your codepen: paste 4 times the current text into the div for the tab. You'll notice the height is limited and no scrollbar appears. Try the same with the official demo and you'll see the same problem again. If the text is too long, it is hidden with no scrolling possible.

One could use a height with xxx px, but if the content of the different tabs differs, than that is not an option, as it is for me on the site i'm currently trying to develop. check this: http://test.listoire.be/discipline/2

It seems my css skills are lacking, because i cannot trace the root of the issue. I've tried adding clearfix classes, setting pretty much everything to height 100%, adding overflow hidden to several elements, nothing works. The only thing that does work is using absolute px values for the height, but that is not an option.

Badlapje commented 7 years ago

added overflow-y: auto which at least gave me a scrollbar. But it looks far too ugly and doesn't resolve the height issue, just a dirty hack atm.

donacross commented 7 years ago

@DanielRuf Sorry for forgetting the row markup, I feel it misleaded the actual issue.

Issue

The original issue was unfortunately not fixed. I guess it's what @Badlapje is trying to say too.

The problem concerns the height of the inner carousel. It doesn't fit the size of the content, it's not vertically responsive, it's fixed to 200px.

Demo

Investigation

Further investigation shows that .carourel-item uses position: absolute;. However, a parent cannot inherit its height from a child absolutely positioned.

That's why Materialize sets the .carousel height during JS initialization. and fails in most cases because of the 200px.

@triskill idea was to reset the carousel height based on its context but it still have some flaws.

From my point of view, it's a design problem which leads to a dead in.

position: absolute; => fixed height => not vertically responsive => find the tallest item at js init => broken if the content changes after init => init again and so on...

Solution

image

@DanielRuf Thank you for your time. Long live Materialize 🎉

Badlapje commented 7 years ago

@donacross thx for pointing out absolute positioning has height implications for the parent. I did not know this.

DanielRuf commented 7 years ago

Flexbox might be indeed a great solution in the near future and make such calculations / estimations in components obsolete.

donacross commented 7 years ago

great solution in the near future

@DanielRuf Does legacy browser support prevents Materialize to move forward ? Flexbox support seems good enough.

What should we do meanwhile ?

DanielRuf commented 7 years ago

IE is still a bit problematic. We could use flexbox for this component but keep a fallback for IE and other browsers.

atemiz commented 7 years ago

For Full Width Use col s12 class

For Auto Height Instead of 200px .tabs-content .carousel-item { height: auto; }

DanielRuf commented 7 years ago

@atemiz that is definitely a much cleaner solution. Maybe we could add some classes for this.

teoxoy commented 6 years ago

I stumbled across this issue as well and I figured I would leave my workaround here.

The Problem: Having tabs with images will cause the tabs-content to be resized to the size of the image. Explanation of Problem: _setCarouselHeight is called in the constructor and in _handleResize when fullWidth = true (it will be true because the carousel instance is initialized with fullWidth: true in the tabs component ), _setCarouselHeight searches for an img element in the first .carousel-item and sets the height of the carousel to that of the found img. Workaround: Implement your own _setCarouselHeight. Example:

$('#img-0').one('load', () => $('.tabs-content').css('height', $('.carousel-item .row').css('height')))
tc._setCarouselHeight = function() {
    $('.tabs-content').css('height', $('.carousel-item .row').css('height'))
    this._autoScroll()
}

Example Notes: