How to prevent squashing flexbox absolute pane by ChartJs? - css

The code below is simplified version of actual one, but it "correctly" shows the problem -- I have window with T-layout. Top section with toolbar, and below the left with some long content, and the right which should take the remaining space.
I used "absolute" position for the left pane because my first problem was how to scroll long content within pane, this is what I found, so I used it.
On the right there is ChartJs and initially it really takes the remaining space but if I move the mouse over it refreshes the content, resulting in squashing the left pane to zero.
How to prevent it (not using hardcoded sizes, like "min-width: 200px")? As left-right panes sizing goes, my intention is "left -- take all what is necessary, right -- take the rest".
The code:
<!DOCTYPE html>
<head>
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/3.9.1/chart.min.js"></script>
</head>
<body style="background-color: pink; overflow:hidden;margin:0" onload="starter()">
<div style="display: flex;flex-direction:column; height: 100vh;width: 100%">
<!-- TOOLBAR -->
<div style="flex-shrink: 0; flex-grow: 0;">
<button>hello</button>
</div>
<div style="flex-shrink: 0; flex-grow: 1;
display: flex;flex-direction:row; ">
<!-- LEFT PANE -->
<div style="position:relative; background-color: aqua; overflow:scroll;
flex-shrink: 0; flex-grow: 1;">
<div style="position:absolute; width: 100%">
<div>
<h1>
<li>1</li><li>2</li><li>3</li><li>4</li><li>5</li><li>4</li>
<li>7</li><li>8</li><li>9</li><li>10</li><li>11</li><li>1</li>
<li>1</li><li>2</li><li>3</li><li>4</li><li>5</li><li>4</li>
<li>7</li><li>8</li><li>9</li><li>10</li><li>11</li><li>0</li>
</ul>
</h1>
</div>
<div>left</div>
</div>
</div>
<!-- RIGHT PANE -->
<div style="background-color: green; flex-shrink: 0; flex-grow: 1;
display: flex;flex-direction:column;">
<div style="position: relative;flex-shrink: 1; flex-grow: 1;">
<canvas id="bar-chart" style="" ></canvas>
</div>
<div style="flex-shrink: 0; flex-grow: 0;">right</div>
</div>
</div>
</div>
<script>
function starter(){
// https://tobiasahlin.com/blog/chartjs-charts-to-get-you-started/
new Chart(document.getElementById("bar-chart"), {
type: 'bar',
data: {
labels: ["Africa", "Asia", "Europe", "Latin America", "North America"],
datasets: [
{
label: "Population (millions)",
backgroundColor: ["#3e95cd", "#8e5ea2","#3cba9f","#e8c3b9","#c45850"],
data: [2478,5267,734,784,433]
}]
},
options: {
maintainAspectRatio : false,
legend: { display: false },
title: {
display: true,
text: 'Predicted world population (millions) in 2050'
}
}
});
}
</script>
</body>
</html>

So I started from the initial problem -- how to take remaining space and enable scroll there? For two panes there is nice solution with the flex layout: https://stackoverflow.com/a/68516470/210342 but as in my case, when I have nested panes, I couldn't make flex take entire window and only window space (without using this hack with absolute position).
Since I don't know CSS I tried grid approach and it worked right on spot. I simply added "height:100vh" for entire grid container and for given scrollable pane "overflow:auto" and that's it.
Now I have scrolling and well sized chart.
Nice grid generator I used: https://cssgrid-generator.netlify.app/

Related

Slick Slider not fits inside container

I am using a slick slider inside a container.The container has two columns namely col-1 and col-2.
I want it to be side by side ,for that i have used flex but it doesn't work.Can anyone please help me to resolve this issue.My aim is to achieve such a slider where the testimonial text section is fixed and only the right one scrolls.The problem is that when flex is used the testmonial slider boxes get down as aseperate row
$(".testimonial-slider-wrap").slick({
dots: true,
arrows: true,
slidesToShow: 1,
slidesToScroll: 1,
variableWidth: true,
speed: 300,
})
.testimonial-main-wrap {
max-width: 136rem;
margin-left: auto;
}
.testimonial-main-wrap {
display: flex;
flex-wrap: wrap;
}
.testimonial-col-1 {
max-width: 39.5rem;
margin-right: 4.2rem;
}
<section id="testimonial">
<div class="testimonial-main-wrap">
<div class="testimonial-col-1">
<p>What Zaiyna clients say</p>
</div>
<div class="testimonial-col-2">
<div class="testimonial-slider-wrap">
<div class="testimonial-slides">
</div>
</div>
</div>
</div>
</section>
I don't understand exactly what you want to archieve, but try putting width:50% to both col-1 and col-2. This way the two elements can be sharing same row in the screen.

angular - click flexbox grid cell to expand area below with full width

I have something like calendar grid using flexbox inside a ionic 3 project.
The cells are one array
<div class="sb-calendar-wrapper">
<div class="sb-calendar-month">
<div class="sb-calendar-row">
<div class="sb-calendar-cell sb-cell-labels sb-week-day" *ngFor="let day of sbcalendar.dayLabels">
{{day}}
</div>
</div>
<div class="sb-calendar-row">
<div class="sb-calendar-cell sb-cell" *ngFor="let day of calendarDays, let j=index" (click)="openCalendarDay(day)" [ngStyle]="{'height': (day.isOpen) ? '300px' : '60px'}">{{j}}
</div>
</div>
</div>
</div>
.sb-cell {
position: relative;
border-bottom: 1px solid rgba(130, 171, 183, 0.2);
padding: 5px;
height: calc((100vh - 150px)/6);
.sb-calendar-day-list{
position: absolute;
width: 100vw;
left: 0;
top:calc((100vh - 150px)/6);
background: #ccc;
height: calc( 300px - calc((100vh - 150px)/6));
}
}
When I click on any day, i want the "row" to expand to display an area which I can use for e.g. displaying items of that cell.
The problem I'm facing is how to position that list element, so that i will fill the entire space or width. With position:relative of the cell I can position everything fine except for the left:0, which doesnt work for most cells.
In summary when i click any day, a box that fills the entire view width should expand. thanks for any suggestions!
EDIT1
I don't want to create manual rows after each n-cell. The cell array should stay as a single array while the flexitem widths controls how many items are in each row.
I think you can organize those days on the same line as a row.
At the end of each row, you can add a place holder div with an ng-if condition.
Whenever you click on a day of that row, you can check the row index for showing the div or not. That div will hold an area that you want.
html:
<div class="flexbox-row" ng-repeat="row in rows track by $index">
<div class="flexbox-col clickable" ng-click="showRow($index)">
1
</div>
<div class="flexbox-col clickable" ng-click="showRow($index)">
2
</div>
<div class="flexbox-col clickable" ng-click="showRow($index)">
3...
</div>
<!-- Place holder div -->
<div ng-if="showRow() === $index">
<div data-custom-directive></div>
</div>
</div>
Show row code:
scope.showRow = function ($index) {
// Return activeRow
if ($index === undefined) {
return scope.activeRow;
}
// Hide if same row
if ($index === scope.activeFlight) {
scope.activeRow = null;
return;
}
// Show row
scope.activeRow = parseInt($index);
};

Bootstrap affix taller than content, scroll fail

I'm having the same problem the author of this question exhibits with affix, specifically the authors comment on the accepted answer. The answerer provides a secondary solution, but this is unsatisfactory.
The issue occurs when all of the following conditions are present:
Affixed div is taller than view port
Affixed div is tallest part of page
User scrolls past affix-top
It is demonstrated in this JSFiddle: https://jsfiddle.net/g1ns9k8o/3/ with the following code:
CSS:
.top-bit { height: 100px; }
.sidebar { width: 200px; padding: 10px; }
.sidebar.affix { top: 10px; }
HTML:
<div class="top-bit">
</div>
<div class="row">
<div class="col-xs-9">
<!-- short content -->
</div>
<div class="col-xs-3">
<div class="sidebar" data-spy="affix" data-offset-top="100">
<!-- long content -->
</div>
</div>
</div>
I had this problem and ran into the jerky scroll movement. To fix it, I used JavaScript to compare the height of the affixed element to the element it is sitting next to. If the affixed height is less than the content height, set the affix. Otherwise, just let the affixed element sit where it is.
So, say it's a sidebar that I'm fixing next to a content element.
// Pseudocode
if (sidebar.height < content.height) {
$(sidebar).affix({});
}

Bootstrap Element 100% Width

I want to create alternating 100% colored blocks. An "ideal" situation is illustrated as an attachment, as well as the current situation.
Desired setup:
Currently:
My first idea was to create an div class, give it a background color, and give it 100% width.
.block {
width: 100%;
background: #fff;
}
However, you can see that this obviously doesn't work. It's confined to a container area. I tried to close the container and that didn't work either.
The container class is intentionally not 100% width. It is different fixed widths depending on the width of the viewport.
If you want to work with the full width of the screen, use .container-fluid:
Bootstrap 3:
<body>
<div class="container-fluid">
<div class="row">
<div class="col-lg-6"></div>
<div class="col-lg-6"></div>
</div>
<div class="row">
<div class="col-lg-8"></div>
<div class="col-lg-4"></div>
</div>
<div class="row">
<div class="col-lg-12"></div>
</div>
</div>
</body>
Bootstrap 2:
<body>
<div class="row">
<div class="span6"></div>
<div class="span6"></div>
</div>
<div class="row">
<div class="span8"></div>
<div class="span4"></div>
</div>
<div class="row">
<div class="span12"></div>
</div>
</body>
QUICK ANSWER
Use multiple NOT NESTED .containers
Wrap those .containers you want to have a full-width background in a div
Add a CSS background to the wrapping div
Fiddles: Simple: https://jsfiddle.net/vLhc35k4/ , Container borders: https://jsfiddle.net/vLhc35k4/1/
HTML:
<div class="container">
<h2>Section 1</h2>
</div>
<div class="specialBackground">
<div class="container">
<h2>Section 2</h2>
</div>
</div>
CSS: .specialBackground{ background-color: gold; /*replace with own background settings*/ }
FURTHER INFO
DON'T USE NESTED CONTAINERS
Many people will (wrongly) suggest, that you should use nested containers. Well, you should NOT.
They are not ment to be nested. (See to "Containers" section in the docs)
HOW IT WORKS
div is a block element, which by default spans to the full width of a document body - there is the full-width feature. It also has a height of it's content (if you don't specify otherwise).
The bootstrap containers are not required to be direct children of a body, they are just containers with some padding and possibly some screen-width-variable fixed widths.
If a basic grid .container has some fixed width it is also auto-centered horizontally.
So there is no difference whether you put it as a:
Direct child of a body
Direct child of a basic div that is a direct child of a body.
By "basic" div I mean div that does not have a CSS altering his border, padding, dimensions, position or content size. Really just a HTML element with display: block; CSS and possibly background.
But of course setting vertical-like CSS (height, padding-top, ...) should not break the bootstrap grid :-)
Bootstrap itself is using the same approach
...All over it's own website and in it's "JUMBOTRON" example:
http://getbootstrap.com/examples/jumbotron/
This is how you can achieve your desired setup with Bootstrap 3:
<div class="container-fluid">
<div class="row"> <!-- Give this div your desired background color -->
<div class="container">
<div class="row">
<div class="col-md-12">
... your content here ...
</div>
</div>
</div>
</div>
</div>
The container-fluid part makes sure that you can change the background over the full width. The container part makes sure that your content is still wrapped in a fixed width.
This approach works, but personally I don't like all the nesting. However, I haven't found a better solution so far.
There is a workaround using vw. Is useful when you can't create a new fluid container.
This, inside a classic 'container' div will be full size.
.row-full{
width: 100vw;
position: relative;
margin-left: -50vw;
left: 50%;
}
After this there is the sidebar problem (thanks to #Typhlosaurus), solved with this js function, calling it on document load and resize:
function full_row_resize(){
var body_width = $('body').width();
$('.row-full').css('width', (body_width));
$('.row-full').css('margin-left', ('-'+(body_width/2)+'px'));
return false;
}
In bootstrap 4, you can use 'w-100' class (w as width, and 100 as 100%)
You can find documentation here:
https://getbootstrap.com/docs/4.0/utilities/sizing/
If you can't change the HTML layout:
.full-width {
width: 100vw;
margin-left: -50vw;
left: 50%;
}
<div class="container">
<div class="row">
<div class="col-xs-12">a</div>
<div class="col-xs-12">b</div>
<div class="col-xs-12 full-width">c</div>
<div class="col-xs-12">d</div>
</div>
</div>
Demo: http://www.bootply.com/tVkNyWJxA6
Sometimes it's not possible to close the content container.
The solution we are using is a bit different but prevent a overflow because of the
firefox scrollbar size!
.full-width {
margin-top: 15px;
margin-bottom: 15px;
position: relative;
width: calc(100vw - 10px);
margin-left: calc(-50vw + 5px);
left: 50%;
}
Here is a example: https://jsfiddle.net/RubbelDeKatz/wvt9253q
Instead of
style="width:100%"
try using
class="col-xs-12"
it will save you 1 character :)
Sorry, should have asked for your css as well. As is, basically what you need to look at is giving your container div the style .container { width: 100%; } in your css and then the enclosed divs will inherit this as long as you don't give them their own width. You were also missing a few closing tags, and the </center> closes a <center> without it ever being open, at least in this section of code. I wasn't sure if you wanted the image in the same div that contains your content or separate, so I created two examples. I changed the width of the img to 100px simply because jsfiddle offers a small viewing area. Let me know if it's not what you're looking for.
content and image separate: http://jsfiddle.net/QvqKS/2/
content and image in same div (img floated left): http://jsfiddle.net/QvqKS/3/
I would use two separate 'container' div as below:
<div class="container">
/* normal*/
</div>
<div class="container-fluid">
/*full width container*/
</div>
Bare in mind that container-fluid does not follow your breakpoints and it is a full width container.
I'd wonder why someone would try to "override" the container width, since its purpose is to keep its content with some padding, but I had a similar situation (that's why I wanted to share my solution, even though there're answers).
In my situation, I wanted to have all content (of all pages) rendered inside a container, so this was the piece of code from my _Layout.cshtml:
<div id="body">
#RenderSection("featured", required: false)
<section class="content-wrapper main-content clear-fix">
<div class="container">
#RenderBody()
</div>
</section>
</div>
In my Home Index page, I had a background header image I'd like to fill the whole screen width, so the solution was to make the Index.cshtml like this:
#section featured {
<!-- This content will be rendered outside the "container div" -->
<div class="intro-header">
<div class="container">SOME CONTENT WITH A NICE BACKGROUND</div>
</div>
}
<!-- The content below will be rendered INSIDE the "container div" -->
<div class="content-section-b">
<div class="container">
<div class="row">
MORE CONTENT
</div>
</div>
</div>
I think this is better than trying to make workarounds, since sections are made with the purpose of allowing (or forcing) views to dynamically replace some content in the layout.
Though people have mentioned that you will need to use .container-fluid in this case but you will also have to remove the padding from bootstrap.
The following answer is not exactly optimal by any measure, but I needed something that maintains its position within the container whilst it stretches the inner div fully.
https://jsfiddle.net/fah5axm5/
$(function() {
$(window).on('load resize', ppaFullWidth);
function ppaFullWidth() {
var $elements = $('[data-ppa-full-width="true"]');
$.each( $elements, function( key, item ) {
var $el = $(this);
var $container = $el.closest('.container');
var margin = parseInt($container.css('margin-left'), 10);
var padding = parseInt($container.css('padding-left'), 10)
var offset = margin + padding;
$el.css({
position: "relative",
left: -offset,
"box-sizing": "border-box",
width: $(window).width(),
"padding-left": offset + "px",
"padding-right": offset + "px"
});
});
}
});
This must work (Mobile phone as well as Desktop screen):
class: alignfull and class: img-fluid will do the magic.
<div class="alignfull">
<img class="img-fluid" style="background-size: cover;
background-position: center ;
background-repeat: no-repeat;
height: auto;
min-width: 100%;
width: -moz-available; "
src="{{ $image->image }}" alt="An image">
</div>

Div with scrollbar inside div with position:fixed

I have a div with position:fixed that is my container div for some menus. I've set it to top:0px, bottom:0px to always fill the viewport. Inside that div I want to have 2 other divs, the lower one of which contains lots of lines and has overflow:auto. I would expect that it would be contained within the container div, but if there are too many lines it simply expands outside the fixed div. Below is my code and a screenshot to clarify:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>MyPlan</title>
<meta name="X-UA-COMPATIBLE" value="IE=8" />
<style type="text/css">
#outerfixed { position:fixed; width:200px; background-color:blue; padding:5px; top:0px; bottom:30px;}
#innerstatic1 { width:100%; background-color:yellow; height:100px;}
#innerstatic2 { overflow:auto; background-color:red; width:100%;}
</style>
</head>
<body>
<div id="outerfixed">
<h3>OUTERFIXED</h3>
<div id="innerstatic1">
<h3>INNERSTATIC1</h3>
</div>
<div id="innerstatic2">
<h3>INNERSTATIC2</h3>
line<br />
...lots of lines
line<br />
</div>
</div>
</body>
</html>
Is there any way for me to do this? Again, I want #innerstatic2 to be properly contained within #outerfixed and get scrollbars if it gets bigger than the space it has inside #outerfixed.
I know there are some possibilites to hack around this by also fixing #innerstatic2, but I would really like it to be within the flow inside #outerfixed if possible, so that if I move #outerfixed somewhere, the inner element would come with it.
EDIT: I know I can set overflow:auto on the #outerfixed and get a scrollbar on the whole thing, but I specifically want a scrollbar just on #innerstatic2, it is a grid and I want to scroll just the grid.
Anyone? Possible?
There's a two-step solution for this, but it comes at something of a cost:
Add overflow-y: scroll; to the css for #innerstatic2.
define a height (or max-height) for #innerstatic2, otherwise it won't overflow, it'll just keep increasing its height (the default for a div is height: auto).
Edited because I just can't stop myself, sometimes.
I've posted a demo on jsbin to show a jQuery implementation of this, which will calculate a height for you (it's not generalised, so it'll only work with your current html).
(function($) {
$.fn.innerstaticHeight = function() {
var heightOfOuterfixed = $('#outerfixed').height(),
offset = $('#innerstatic2').offset(),
topOfInnerstatic2 = offset.top,
potentialHeight = heightOfOuterfixed - topOfInnerstatic2;
$('#innerstatic2').css('height',potentialHeight);
}
})(jQuery);
$(document).ready(
function() {
$('#innerstatic2').innerstaticHeight();
}
);
I solved it by giving absolute position to the ul and height 100%
ul {
overflow-y: scroll;
position: absolute;
height: 100%;
}
check out this FIDDLE
overflow-y:scroll;
And add this for iOS devices. It does give a better scroll using touch. The overflow-y needs to be scroll! for secure reasons. auto wont work for some people. or at least thats what i heard.
-webkit-overflow-scrolling: touch;
you should set height for outerfixed and max-height for innerstatic2
see this might be helpful DEMO
It is the container div who has to be with the overflow:auto attribute. In this case, the #outerfixed div
The only way I figure, is to set innerstatic2 to absolute position (so you can use top and bottom to size it in relation to outerfixed), then inside innerstatic2 create another div where you put your text in. Then you give innerstatic2 the "overflow: auto;" indication. The drawback of this method, that innerstatic2 does not move down, when innerstatic1 grows, since it has to be position absolutely. If it needs to move, it must be "position: relative", but then you need to set a fixed height for it. So either way you have to settle for a compromise.
Once all browsers support the newer CSS3 features, like the calculation support, there will be better options to do this, without these drawbacks.
Not ideal, but this should get you 90% of they way
<div style="position:fixed; bottom:1px; left:5em; height: 20em; width:20em; background-color:blue;">
<div style ="width:15em; background-color: green;">
Title
</div>
<div style ="background-color:yellow; max-height:80%; width:15em; overflow:auto;">
<div style="height:100em; background-color:red; width:10em;">
scroll<br/>
scroll<br/>
scroll<br/>
</div>
</div>
</div>
So I couldn't do with the fixed position but I got the desired effect with the position as relative.
Try this
<div class="parent" style = "overflow: scroll; position: relative; width: content-box"">
<div class="scrollable-child" >
//Your content here
</div>
</div>
I used this in one of my vuejs projects
<template>
<v-flex class=" d-flex flex-column " style="overflow: scroll; position: relative; width: content-box">
//FIXED HEAD
<v-flex class="pt-10" style="position: fixed; background-color: black;width: 25.2em;z-index: 1;border-radius: 20px 20px 0 0">
<TextView class="mx-4" text="Thur 28, 2021" size="24" bold :color="colors.primaryText"/>
<TextView :text="`${order.totalOrder()} Items`" size="24" bold :color="colors.primaryText" class="my-2 mx-4"/>
<v-divider dark style="height: 5px" class="max-4" />
</v-flex>
//SCROLABLE LIST ITEMS
<v-flex class=" mx-4 d-flex flex-column justify-end " style="margin-top: 100px;padding-bottom: 100px; padding-top: 50px">
<!-- <TextView :text="receipt" :color="colors.primaryText"/>-->
<ProductComponent type="cartItem" v-for="(product,index) in order.products" :key="`order_item_${index}`" :product="product" :invert-theme="true" #onAdd="addOneMore(index)" #onRemove="removeOne(index)" />
</v-flex>
//BOTTOM FIXED BTN
<v-flex class="d-flex flex-column justify-end mb-2 xs12 mx-4 " style="max-height: 100px; position: fixed; bottom: 30px; width: 23em" >
<v-btn block ref="renderBtn" #click="renderReceipt()" depressed min-height="60" style="border-radius: 20px">
<TextView text="Order" bold/>
</v-btn>
</v-flex>
</v-flex>
</template>

Resources