I have a web page that sequentially adds various sizes of fixed width panels (flex: none) from left to right as the user drills down. When the panels reach (or will overreach) the end of the page I want the first panel (and subsequent panels) to 'scroll' to the left (overflow hidden is acceptable, partial content visible is ok)
Originally aligned left as follows when panel ONE then TWO, etc is added
=============================================================
= =
= ----------- ----------- ----------- ----------- =
= | | | | | | | | =
= | ONE | | TWO | | THREE | | FOUR | =
= | | | | | | | | =
= ----------- ----------- ----------- ----------- =
= =
==============================================================
Then when FIVE is added it will overreach the end of the page so panel ONE is scrolled out of view (overflow hidden is ok)
=============================================================
= =
=-- ----------- ----------- ----------- ----------- =
= | | | | | | | | | =
= | | TWO | | THREE | | FOUR | | FIVE | =
= | | | | | | | | | =
=-- ----------- ----------- ----------- ----------- =
= =
=============================================================
Conversely, when panel FIVE (or any other) is removed, then ONE should go back into view.
So far I have this:
<div class="container-fluid">
<div class="panel-container">
<div class="panel">
1 of 4
</div>
<div class="panel">
2 of 4
</div>
<div class="panel">
3 of 4
</div>
</div>
</div>
.panel-container {
justify-content: flex-end;
margin-top: 1rem;
width: 100%;
display: flex;
width: fit-content;
}
.panel {
border: solid 1px #6c757d;
padding: 10px;
flex: none;
width:300px;
}
I've also tried this:
.panel-container {
margin-top: 1rem;
justify-content: flex-end;
width: auto;
right: inherit;
display: inline-flex;
}
My jsFiddle
My css only works when I don't set the width of the last panel, but then the width expands to fit the remaining space which is not what I want. Prefer a css solution using flex box, but if that's not possible then anything workable would be appreciated
any help would be appreciated!
oh, of course it was so simple in the end (after a bike ride to clear the mind).
margin-right: auto; on the last child. I applied it to all children in case there was some other content there (for example loading spinners, etc to prevent the right margin collapsing)
.panel-container {
display: flex;
justify-content: flex-end;
}
.panel {
flex: 0 0 300px;
border: solid 1px #6c757d;
padding: 10px;
}
.panel-container > :last-child {
margin-right: auto;
}
updated jsfiddle
The only way to do it, tha I know of, is to use JavaScript's .scrollLeft:
https://codepen.io/agakesik/pen/WNrEQdP
document.getElementsByClassName('panel-container').scrollLeft = 9999999;
There's too much in your code. Simplify it.
.panel-container {
display: flex;
justify-content: flex-end;
}
.panel {
flex: 0 0 300px;
border: solid 1px #6c757d;
padding: 10px;
}
<div class="container-fluid">
<div class="panel-container">
<div class="panel">1 of 4</div>
<div class="panel">2 of 4</div>
<div class="panel">3 of 4</div>
</div>
</div>
revised fiddle
Related
Disclaimer: I'm not sure how to address this issue please be kind and suggest another title I'll edit
Situation
I have a responsive design mobile / desktop with blocks:
Mobile
| block1 |
| block2 |
| clientInfos |
| equipmentInfos |
| history |
Desktop
| clientInfos | block1 |
| equipmentInfos | block2 |
| - | history |
Problem
The thing is I dont what to setup this as a grid / table because this page as multiple states where height are heavly dynamics.
Some samples of possible renders:
| clientInfos | block1 |
| clientInfos | block2 |
| clientInfos | history |
| clientInfos | - |
| clientInfos | - |
| equipmentInfos | - |
| clientInfos | block1 |
| equipmentInfos | block1 |
| - | block1 |
| - | block2 |
| - | history |
My main issue is : clientInfos and equipmentInfos are in the middle of the list in mobile design. So, I can wrap them in a single div. But not other items.
Note, my devs are mobile first.
Best try so far
My best try is to wrap clientInfos and equipmentInfos then use a grid-template:
function addSpace (e) {
e.target.append(document.createElement("br"))
}
.content {
display: flex;
flex-direction: column;
gap: 22px;
}
/* media screen to 1px to show my issue */
#media screen and (min-width: 1px) {
.content {
display: grid;
grid-template-areas:
"clientAndEquipment block1"
"clientAndEquipment block2"
"clientAndEquipment history";
}
}
.block1 { grid-area: block1 }
.block2 { grid-area: block2 }
.clientAndEquipment {
/* To keep the parent flow */
display: flex;
flex-direction: column;
gap: 22px;
grid-area: clientAndEquipment
}
.history { grid-area: history }
.block { background: pink; padding: 5px; }
<div class="content">
<div class="block1 block">BLOCK1</div>
<div class="block2 block">BLOCK2</div>
<div class="clientAndEquipment">
<div class="client block" onclick="addSpace(event)">CLIENT click here to add spaces</div>
<div class="equipment block">EQUIPMENT</div>
</div>
<div class="history block">HISTORY</div>
</div>
The problem with this approach is the case when client is to big, it result to other block expanding as 33% height each. It's not ideal.
Note: I tried to had an extra "clientAndEquipment -" to the template-grid-areas but it add an extra blank line due to gap: 22px which I wanna keep.
Question
Did you see a better integration of this design according to constraints mention ?
Note: js related answers are not better imo.
I found a solution using plain old float property re-ordering my div.
workflow
Put all div that "could" go left on top of the flow (in the .content).
<div class="wrapper">
<div class="clientInfo left"></div>
<div class="equipmentInfo left"></div>
<div class="block1 main"></div>
<div class="block2 main"></div>
<div class="history main"></div>
</div>
mobile
Display wrapper as flex then apply an order on each item.
.wrapper { display: flex; flex-direction: column; }
.clientInfo { order: 3; }
.equipmentInfo { order: 4; }
.block1 { order: 1; }
.block2 { order: 2; }
.history { order: 5; }
desktop
Display wrapper as block then:
// all media query desktop ...
.wrapper {
--sidebar-width: 400px;
--sidebar-gap: 22px;
display: block;
}
.left {
float: left;
width: var(--sidebar-width);
margin-right: var(--sidebar-gap);
clear: both; /* <-- set the lefties as columns */
}
.main {
margin-left: calc(var(--sidebar-width) + var(--sidebar-gap));
}
And Voila!
Is it possible to use order: 2 and have that flex item be positioned in order without setting order on the other items?
div elements without order are shown in DOM order, however the following won't move the order: 2 element in between the DOM-ordered elements because the elements don't have an order specified.
div.flex-container {
display: flex;
}
div.flex-container div {
flex-basis: 10px;
}
div.order-2 {
order: 2;
-webkit-order: 2;
}
<div class="flex-container">
<div>a</div>
<div>b</div>
<div>c</div>
<div>d</div>
<div class="order-2">1</div>
</div>
Is it possible to order the .order-2 div such that it is between the DOM-ordered elements, such that "ab1cd" is shown?
+-- display: flex; -----------------------------------------------------------------------+
| |
| +-----------+ +-----------+ +-----------+ +-----------+ +-----------+ |
| | | | | |XXXXX XXXXX| | | | | |
| | a | | b | |XXXX 1 XXXX| | c | | d | |
| | | | | |XXXXX XXXXX| | | | | |
| +-----------+ +-----------+ +-----------+ +-----------+ +-----------+ |
| |
+-----------------------------------------------------------------------------------------+
The default order value of a flex item is 0. If you do not want to specify an order value for all elements, you will need to move the elements around.
Knowing that the default value is 0 you could add an order value of 1 to the items you want to come after your last item. It is no problem for them to have the same order value, because elements of the same order value are displayed in the order in which they appear in the source code.
It is also possible to move an element all the way to the front by adding an order value of -1 to it.
Here is an example of what you could do to reorder your elements without specifying an order value for each element.
Basically just add a class with a higher order value to those elements you want to appear after the other elements.
.flex-container {
padding: 0;
margin: 0;
list-style: none;
display: -webkit-box;
display: -moz-box;
display: -ms-flexbox;
display: -webkit-flex;
display: flex;
-webkit-flex-flow: row wrap;
justify-content: space-around;
}
.flex-item {
background: black;
padding: 2px;
width: 50px;
height: 50px;
margin-top: 10px;
line-height: 50px;
color: white;
font-weight: bold;
font-size: 3em;
text-align: center;
}
.reorder {
order: 1;
}
<ul class="flex-container">
<li class="flex-item">A</li>
<li class="flex-item">B</li>
<li class="flex-item reorder">C</li>
<li class="flex-item reorder">D</li>
<li class="flex-item">1</li>
</ul>
I have a container of a fixed size, containing a vertical list of blocks of varying heights .
I would like to hide all blocks that does not fit completely within the container.
So assuming something like this:
#container{
height: 150px;
width: 220px;
border:1px solid green;
padding:10px;
overflow: hidden;
}
.inner{
border:1px solid blue;
height: 50px;
width: 200px;
margin: 10px;
text-align: center;
vertical-align: middle;
line-height: 50px;
}
<div id="container" >
<div class="inner">A</div>
<div class="inner">B</div>
<div class="inner">C</div>
<div class="inner">D</div>
</div>
(See: http://jsfiddle.net/TSCzS/)
I get something like this:
+-------------+
| |
| +-------+ |
| | A | |
| +-------+ |
| |
| +-------+ |
| | B | |
| +-------+ |
| |
| +-------+ |
+--| C |--+
+-------+
+-------+
| D |
+-------+
I do not want to just have the C block clipped:
(as when simply using overflow:hidden on the container)
+-------------+
| |
| +-------+ |
| | A | |
| +-------+ |
| |
| +-------+ |
| | B | |
| +-------+ |
| |
| +-------+ |
| | C | |
+-------------+
but instead, the blocks C and D should be hidden like this:
+-------------+
| |
| +-------+ |
| | A | |
| +-------+ |
| |
| +-------+ |
| | B | |
| +-------+ |
| |
| |
+-------------+
How can I do this?
My application for this is that I have a full screen browser window (in a digital signage application) showing the "latest news". The units have no input devices, so scrolling is not possible.
A similar question, but without a working solution:
Hide block which does not fit container height
Thanks.
The only way I can imagine a solution is via JavaScript. CSS itself wont help.
Here's an update of your fiddle: http://jsfiddle.net/bukfixart/TSCzS/1/
This snippet selects all clipping elements and hides them.
$('.inner', '#container').filter(function() {
return $('#container').offset().top + $('#container').height() < $(this).offset().top + $(this).height();
}).hide();
For this solution you need to use jQuery
edit:
For all the pure CSS enthusiasts ;-)
http://jsfiddle.net/bukfixart/CfMer/
I tried a solution without javascript and used css3 transformations instead. Therefore some markup changes are necessary
<div id="outercontainer" >
<div id="container" >
<div class="outer">
<div class="inner">A</div>
</div>
<div class="outer">
<div class="inner">B</div>
</div>
<div class="outer">
<div class="inner">C</div>
</div>
<div class="outer">
<div class="inner">D</div>
</div>
<div style="clear:left;"></div>
</div>
</div>
And here's the a little bit stranger style code
#outercontainer {
width:240px; /* container width + padding */
height:170px; /* container height + padding */
border:1px solid green;
}
#container{
height: 220px; /* container width ^^ */
width: 150px; /* container height ^^ */
padding:10px;
overflow: hidden;
position:relative;
left:35px; /* half of difference from width + padding to outer container width */
top:-35px; /* half of difference from height + padding to outer container height */
-webkit-transform:rotate(90deg);
}
.outer{
float:left;
height:202px; /* width of the inner box + border */
width:52px; /* height of the inner box + border */
margin:10px 10px 10px 0px;
line-height:200px; /* width of the inner box */
vertical-align:middle;
-webkit-transform:rotate(-90deg);
}
.inner{
border:1px solid blue;
height: 50px;
width: 200px;
text-align: center;
vertical-align: middle;
line-height: 50px;
display:inline-block;
position: relative;
left: -75px; /* half of difference between width and height */
}
I have 3 divs with display:inline-block style. I want to set their height value so that it matches the one with the highest value. I also want to set height values auto. I've tried to show visually what I want to get below. Is this possible with pure CSS?
----- ----- ----- ----- ----- -----
| | | | | | | | | | | |
----- | | | | ==> | | | | | |
----- | | | | | | | |
----- ----- ----- -----
With CSS you can set the inner divs to be display: table-cell and the outer one to be display: table
Demo: http://jsfiddle.net/maniator/C2dNu/
HTML:
<div id='out'>
<div class='red'></div>
<div class='blue'></div>
<div class='green'></div>
</div>
CSS:
.red {
background: red;
height: 60px;
}
.blue {
background: blue;
height: 160px;
}
.green {
background: green;
height: 80px;
}
#out {
display: table;
width: 500px;
}
#out > div {
display: table-cell;
width: 33%;
}
With JS, it can be done with Equalize.js. I don't know a pure CSS solution though.
The basic question is: How can a be shrink-to-fit over an element while itself containing other elements?
The goal is to have a (centered) menu over an (centered) image, which´s width and height shall relate to the images dimensions.
All of it being responsive, meaning no absolute sizes!
Here´s the sample code:
<div id="menu">
<img src="picture.jpg" />
<div id="left">
test1
</div>
<div id="right">
test2
</div>
</div>
#menu{
position:relative;
display: table; /*tried inline-block as well */
text-align: center;
line-height: 1;
}
#menu img{
height: 90%;
position:relative;
}
#left{
width: 46%;
background-color: #ffcdcc;
float: left;
text-align: right;
}
#clear{
clear: both;
}
#right{
width: 46%;
background-color: #324344;
float: right;
text-align: left;
}
and this is what it´s supposed to look like:
____________________________________
| |
| ------------------------------ |
| | | |
| | p i c t u r e | |
| | | |
| | | |
| | | |
| | | |
| | left <button> right | |
| | | |
| ------------------------------ |
| |
------------------------------------
The height/width ratio of the picture is always the same. It´s total size depends on the users window though.
I just can´t get the "menu" div to wrap around the and the "left" and "right" divs be positionable at the same time.
Is this even possible? I´m not even talking about browser compatibiliy yet...
See if this works: http://jsfiddle.net/sdvnh/1/
Changes:
#menu {
display: block;
}
#menu img{
height: 90%;
width: 90%;
}