ui router sliding side bar with flex - css

I want to be able to have a side-bar slide in. I have almost gotten there but I am having issues with the main view snapping into place while the side bar slides in. I have created this Plunkr to demonstrate the problem I'm having. Notice how the body doesn't move with the side-panel. How can I make this work as I expect?
body:
<div class="container">
<div class="child">
<a href ui-sref="main.sidePanel">show side panel</a>
</div>
<div ui-view class="slide"></div>
</div>
side-panel:
<div class="side-panel-body">
<a href ui-sref="main">hide side panel</a>
</div>
css:
.container {
display: flex;
height: 400px;
padding: 20px 0;
}
.child {
background: yellow;
flex: auto;
}
.side-panel-body {
width: 400px;
height: 100px;
background: lightgray;
}
.slide.ng-enter,
.slide.ng-leave {
transition: all 2s ease;
}
.slide.ng-enter {
transform: translate(100%, 0);
}
.slide.ng-enter-active {
transform: translate(0, 0);
}
.slide.ng-leave {
transform: translate(0, 0);
}
.slide.ng-leave-active {
transform: translate(100%, 0);
}

Without going into too much detail about transformations. The easy answer is that translating a DOM element has no effect on other DOM elements.
So you have a flexbox with 2 divs in it. They're functioning as expected. When you expand the window, the left div expands to fill, as it's set to flex: auto, while the right div stays at 400px of fixed width.
When you transform: translate the righthand div, all you are doing is visually moving it. It's container, as well as the lefthand div, still consider it to be exactly where it started. That is, until you actually hide it or remove it. When the right hand div is hidden, then you can see the lefthand div fill up the flex-box.
So to achieve what you want, you'd need to either animate both divs, lefthand for size, and righthand for translation. Or actually change the width of the righthand div, allowing the transition: all 2s ease;to handle the animation for you.

Thanks to #CH Buckingham I came up with a solution. It's not exactly how I imagined, but it works just fine and really isn't THAT hacky. This allows you to toggle the sidebar with a scope variable but you can have the flexibility of content with ui-router.
<div class="container">
<div class="child">
<a href ui-sref="main.sidePanel">show side panel</a>
</div>
<div ng-show="showSidebar" class="sidebar">
<div ui-view class="uiview"></div>
</div>
</div>
css (less):
.container {
display: flex;
}
.child {
flex: auto;
}
.sidebar {
width: 1000px; // for some reason this acts more like a max-width for the sidebar. The actually width matches the size of the ui-view.
&.ng-hide-add, &.ng-hide-remove {
transition: all ease .8s;
overflow-x: hidden;
}
&.ng-hide {
width: 0;
}
}

Related

CSS flip card: How can I activate the flip via tab, so it is keyboard accessible?

I have found some great tuts on how to make a flip card with CSS. My question though is how to make this keyboard accessible. In other words, for a user with a disability who only is using a keyboard, hopefully they would be able to just use the tab button (thus focus), and the card would turn over to show the back content and allow tabbing to select links on the card's back.
I Googled this and found some suggestions (please see the jsfiddle below where I tried them), but I couldn't get success.
Here is a great website that has this functionality, but I don't know how they made it work:
https://businessexpress.maryland.gov/
Notice that if you hold tab down on the above page, eventually your cards will flip, and you can then tab through the links on them. For example, for the first flip card there is a link "/plan", and then it has sublinks like "/plan/create-business-plan", etc.
Please notice that I tried to put in some CSS on line 21 that would affect the "active" and "focus" pseudo classes. But only hovering makes the card flip. I wish that tabbing onto any of the links would flip the card, like in the maryland.gov example above.
I've included a jsfiddle here (there is a little input element so you can start tabbing from it):
https://jsfiddle.net/anrbhcmv/
HTML:
<div id="content">
<h1>Small Business Resources</h1>
<input type="text">
<br><br>
<div class="flip-card">
<div class="flip-card-inner">
<a href="#" id="flip-card-inner">
<div class="flip-card-front">
<div>Card-front content</div>
</div>
</a>
<div class="flip-card-back">
Google
<div>Text</div>
</div>
</div>
</div>
</div><!-- end #content -->
CSS:
/* The flip card container - set the width and height to whatever you want. We have added the border property to demonstrate that the flip itself goes out of the box on hover (remove perspective if you don't want the 3D effect */
.flip-card {
background-color: transparent;
width: 300px;
height: 200px;
// border: 1px solid #f1f1f1;
// perspective: 1000px; /* Remove this if you don't want the 3D effect */
}
/* This container is needed to position the front and back side */
.flip-card-inner {
position: relative;
width: 100%;
height: 100%;
text-align: center;
transition: transform 0.8s;
transform-style: preserve-3d;
}
/* Do an horizontal flip when you move the mouse over the flip box container */
.flip-card:hover .flip-card-inner, .flip-card:active .flip-card-inner, .flip-card:focus .flip-card-inner{
transform: rotateY(180deg);
}
/* Position the front and back side */
.flip-card-front, .flip-card-back {
position: absolute;
width: 100%;
height: 100%;
-webkit-backface-visibility: hidden; /* Safari */
backface-visibility: hidden;
}
/* Style the front side (fallback if image is missing) */
.flip-card-front {
background-color: #008CCC;
background-color: azure;
color: white;
color: black;
}
/* Style the back side */
.flip-card-back {
background-color: #99CC66;
color: white;
transform: rotateY(180deg);
}
You can use :focus-within pseudo-class:
.flip-card:focus-within .flip-card-inner
/* The flip card container - set the width and height to whatever you want. We have added the border property to demonstrate that the flip itself goes out of the box on hover (remove perspective if you don't want the 3D effect */
.flip-card {
background-color: transparent;
width: 300px;
height: 200px;
// border: 1px solid #f1f1f1;
// perspective: 1000px; /* Remove this if you don't want the 3D effect */
}
/* This container is needed to position the front and back side */
.flip-card-inner {
position: relative;
width: 100%;
height: 100%;
text-align: center;
transition: transform 0.8s;
transform-style: preserve-3d;
}
/* Do an horizontal flip when you move the mouse over the flip box container */
.flip-card:hover .flip-card-inner,
.flip-card:focus-within .flip-card-inner,
.flip-card:active .flip-card-inner,
.flip-card:focus .flip-card-inner {
transform: rotateY(180deg);
}
/* Position the front and back side */
.flip-card-front,
.flip-card-back {
position: absolute;
width: 100%;
height: 100%;
-webkit-backface-visibility: hidden;
/* Safari */
backface-visibility: hidden;
}
/* Style the front side (fallback if image is missing) */
.flip-card-front {
background-color: #008CCC;
background-color: azure;
color: white;
color: black;
}
/* Style the back side */
.flip-card-back {
background-color: #99CC66;
color: white;
transform: rotateY(180deg);
}
<div id="content">
<h1>Small Business Resources</h1>
<input type="text">
<br><br>
<div class="flip-card">
<div class="flip-card-inner">
<a href="#" id="flip-card-inner">
<div class="flip-card-front">
<div>Card-front content</div>
</div>
</a>
<div class="flip-card-back">
Google
<div>Text</div>
</div>
</div>
</div>
</div>
<!-- end #content -->
Please do not just use focus-within as suggested(*).
It has no support in Internet Explorer, which is a big problem as this question is marked as "accessibility".
Whereas Internet Explorer support wouldn't normally be a problem, around 11% of screen reader users use IE 11 and a further 1.5% use IE 9 and 10..
Also please be aware that around 25% of screen reader users are not blind. so making sure the visual experience matches the screen reader experience is also important (in case you were wondering why it matters if the card rotates for a screen reader user.)
Below is a very rough idea for a workaround that should be fairly flexible, it does rely on the parent item having a unique class as it stands but that could easily be fixed if you have lots of these, it is only an example to get you started.
The below code should be compatible all the way back to IE9 (please check I may have made a minor mistake), increasing your browser coverage from 89% to around 97%, a 10% improvement.
CSS - please also check the adjustments to the CSS, I added two separate items, one is the .flip-card.focus-within .flip-card-inner selector for the class we add to the parent to perform the rotation.
The other is #media (prefers-reduced-motion) to switch off the rotation animation if a user has set their user settings to 'reduced animation', another accessibility improvement.
It is not often I advocate for a JavaScript solution over a CSS one but in this scenario we are still limited by older browsers I am afraid.
function addListeners(parentClass){
var focusableItems = ['a[href]', 'area[href]', 'input:not([disabled])', 'select:not([disabled])', 'textarea:not([disabled])', 'button:not([disabled])', '[tabindex="0"]'];
for (i = 0, leni = focusableItems.length; i < leni; i++) {
var focusableElements = document.querySelectorAll("." + parentClass + " " + focusableItems[i]);
for (j = 0, lenj = focusableElements.length; j < lenj; j++) {
focusableElements[j].addEventListener("focus", function() {
document.querySelector("." + parentClass).classList.add("focus-within");
});
focusableElements[j].addEventListener("blur", function() {
document.querySelector("." + parentClass).classList.remove("focus-within");
});
}
}
}
addListeners("flip-card");
/* The flip card container - set the width and height to whatever you want. We have added the border property to demonstrate that the flip itself goes out of the box on hover (remove perspective if you don't want the 3D effect */
.flip-card {
background-color: transparent;
width: 300px;
height: 200px;
// border: 1px solid #f1f1f1;
// perspective: 1000px; /* Remove this if you don't want the 3D effect */
}
/* This container is needed to position the front and back side */
.flip-card-inner {
position: relative;
width: 100%;
height: 100%;
text-align: center;
transition: transform 0.8s;
transform-style: preserve-3d;
}
/* Do an horizontal flip when you move the mouse over the flip box container */
.flip-card:hover .flip-card-inner, .flip-card:active .flip-card-inner, .flip-card:focus .flip-card-inner{
transform: rotateY(180deg);
}
/* Position the front and back side */
.flip-card-front, .flip-card-back {
position: absolute;
width: 100%;
height: 100%;
-webkit-backface-visibility: hidden; /* Safari */
backface-visibility: hidden;
}
/* Style the front side (fallback if image is missing) */
.flip-card-front {
background-color: #008CCC;
background-color: azure;
color: white;
color: black;
}
/* Style the back side */
.flip-card-back {
background-color: #99CC66;
color: white;
transform: rotateY(180deg);
}
/* New CSS selector */
.flip-card.focus-within .flip-card-inner{
transform: rotateY(180deg);
}
#media (prefers-reduced-motion) {
.flip-card-inner {
transition: transform none;
}
}
<div id="content">
<h1>Small Business Resources</h1>
<input type="text">
<br><br>
<div class="flip-card">
<div class="flip-card-inner">
<a href="#" id="flip-card-inner">
<div class="flip-card-front">
<div>Card-front content</div>
</div>
</a>
<div class="flip-card-back">
Google
<div>Text</div>
</div>
</div>
</div>
</div><!-- end #content -->
(*) Alternative route with polyfill
I found a focus-within polyfill, I haven't checked whether it would work in IE9 and 10 but I would consider it a reasonable compromise to only support IE11 for most companies and it appears to work in IE11.
We still support back to IE9 where we can, hence why I included the above code snippet (plus it is less JS so better for performance).

Display inline-block not growing horizontally with child having padding in per cent

When I put an img tag inside a inline-block element and give padding to it the parent isn't growing as it should.
article {
background: fuchsia;
display: inline-block;
}
img {
padding: 5%;
}
<article>
<img src="https://fakeimg.pl/412x412"/>
</article>
CodePen:
https://codepen.io/Yarmolaev/pen/xxxbeJr
It's the use of percentage value that consider the parent width as reference. Here you have a kind of cycle since the width is also based on the content.
In this case the browser is ignoring the padding to find the width of the container based on its content then the padding is calulated based on that width and added to the image to create the overflow. The browser will not go back to change the container width because it will be an infinte loop.
The only way to fix this is to consider fixed values:
article {
background: fuchsia;
display: inline-block;
}
img {
padding: 10px;
}
<article>
<img src="https://fakeimg.pl/412x412"/>
</article>
More details here: https://www.w3.org/TR/css-sizing-3/#percentage-sizing
This will happen in most of the cases where you use percentage value and where the container size is based on its content (shrink-to-fit behavior).
Another example where the image is taking 50% of its initial width used to define the container size:
article {
background: fuchsia;
float:left;
}
img {
width:50%;
}
<article>
<img src="https://fakeimg.pl/412x412"/>
</article>
Related questions with similar situations:
Why does percentage padding break my flex item?
CSS Grid - unnecessary word break
A hack that works on Chrome if want to keep the use of percentage padding is to consider a non visible animation that will trigger the calculation of width again and you will no more have the overflow:
article {
background: fuchsia;
display: inline-block;
}
img {
padding: 5%;
animation:change 0.3s infinite;
}
#keyframes change{
to {
padding:5.01%;
}
}
<article>
<img src="https://fakeimg.pl/412x412"/>
</article>

How can I ensure that a div without content will get the height of the parent div?

i am trying to create to divs width the outer container set to 1000px and the inner left and right container to 50% each.
Now i have used this code
.leftNav {
#include span-columns( 5 of 10);
background-color:silver;
color:white;
}
.rightNav {
#include span-columns( 5 of 10);
background-color:silver;
color:white;
}
Now somehow if i don't put anything on left nav the right nav takes full 100% width.
How can i set the leftnav or rightnav to maintain at least 50% width even if they are empty?
thanks.
This "issue" doesn't come from Neat, but from CSS itself. To be shown, an empty element require to have a height.You can use one of the following tricks:
Put in your div
Set a height on your div
Set a padding on your div
Here's another trick I like, if you're not using the :after pseudo-element on these div:
.leftNav:after,
.rightNav:after {
content: '.'; // dot will force its parent to have a height
opacity: 0; // dot is hidden
}
You could use css tables.
Setting display:table-cell on both the left and right divs will ensure that each one gets equal height (ie the height of the greater of the two)
FIDDLE
.container {
width: 100%;
display: table;
}
.left {
width: 50%;
display: table-cell;
background: silver;
}
.right {
width: 50%;
display: table-cell;
background: tomato;
}
<div class="container">
<div class="left"></div>
<div class="right">some text</div>
</div>
You can also do:
.leftNav:after,
.rightNav:after {
content: '';
display: inline-block;
}
Then you don't have to deal with any dots which could be confusing to someone else looking at your code.

Css overlapperd click

I'm building a strange div shaped structure and I need a hint to resolve a clicking problem.
This is a jsfiddle to show you the issue.
The structure for each element is:
<div class="views-row">
<div class="diamonds-container">
CONTENT
</div>
</div>
I have a onclick() event on .diamonds-container but the .views-row div of the next element [with red or blue background..] go over the container and stop the click event on it.
I tryed to play with the z-index but I didn't have the expected result.
How can I achieve this structure with a correct click event on diamonds-containers ?
I think I can track the .views-row click with javascript and trigger manually a click on the previous diamonds-container but this will be my final option.
How can I achieve this without javascript?
UPDATE:
I have to position my diamonds like this
so I can't use the #matewka code because I will have the overlaping vertically instead of orizzontally..
There is more than one route for this kind of problem.
If you use the rotation transform anyway, why not rotate the .views-row element to get the bounding box out of the way?
For recent browsers and IE11 there are pointer events. See this updated fiddle.
.views-row {
z-index: 1;
pointer-events: none;
}
.diamonds-container {
z-index: 9;
pointer-events: auto;
}
Here is my approach. I'm not sure if nesting two divs inside each other was for rotating purpose or had some other meaning. Anyway, I did it this way:
.views-row {
width: 130px;
height: 130px;
-webkit-transform: rotate(45deg);
}
.views-row-first {
-webkit-transform-origin: 195px center;
}
.views-row-even {
-webkit-transform-origin: center center;
}
.views-row-odd {
-webkit-transform: rotate(-45deg);
-webkit-transform-origin: -65px center;
}
Each .views-row is rotated and the transform origins are all pointed to the center of the middle div. Notice that the transform-origin values are multiplicities of the half of the width (130px / 2).
See the updated FIDDLE for the complete CSS. I also added a :hover property for .diamonds-container so you can see that they're all clickable.
UPDATE
With the picture you added the problem became much more complicated. But I figured it out.
Hint: If you can't wait for the fiddle - you'll find it at the bottom of the answer.
The idea:
Square boxes are nested twice. Each 2 .diamond boxes are wrapped with the .pair-wrapper div. That div is rotated 45deg and it is repeated few times along its container. Each even .pair-wrapper has increased width to position its right-hand neighbour properly.
A bunch of .pair-wrappers are wrapped with the .line-wrapper. You can add as much .line-wrappers and .pair-wrapper as you want (remember - .pair-wrappers will break into the new line if they don't fit).
Finally, each .line-wrapper has fixed height and hidden overflow to restrict its children area from the top and the bottom. Each .pair-wrapper is positioned relatively and has negative top value.
The solution is based mostly on fixed values, both I could figure out a better idea.
The code
Example HTML markup looks like this:
<div class="line-wrapper line-wrapper-odd">
<div class="pair-wrapper pair-wrapper-odd">
<div class="diamond-box"></div>
<div class="diamond-box"></div>
</div>
<div class="pair-wrapper pair-wrapper-even">
<div class="diamond-box"></div>
<div class="diamond-box"></div>
</div>
<div class="pair-wrapper pair-wrapper-odd">
<div class="diamond-box"></div>
<div class="diamond-box"></div>
</div>
</div>
<div class="line-wrapper line-wrapper-even">
<div class="pair-wrapper pair-wrapper-odd">
<div class="diamond-box"></div>
<div class="diamond-box"></div>
</div>
.....
</div>
.....
And the most important parts from CSS (complete CSS in the fiddle):
.line-wrapper {
height: 170px;
overflow: hidden;
}
.line-wrapper-even {
margin-left: -92px;
}
.pair-wrapper {
width: 130px;
position: relative;
top: -26px;
-webkit-transform: rotate(45deg);
}
.pair-wrapper-odd {
-webkit-transform-origin: 65px 65px;
}
.pair-wrapper-even {
-webkit-transform-origin: 92px 131px;
width: 239px;
}
.diamond-box {
width: 130px;
height: 130px;
}
The fiddle
http://jsfiddle.net/N3V6J/3/

Relative parent DIV to inherit the width of absolute child DIV

I am trying to position a child DIV at the bottom of a parent DIV, but I would also like the contents of the child DIV to help dictate the dimensions of the parent DIV. As I have it right now, the child DIV doesn't affect the width/height of the parent DIV.
Here is a sample of my HTML/CSS code:
//HTML code:
<div id="parent">
<h3>Top Aligned Title</h3>
<div id="child"></div>
</div>
//CSS code:
#parent {
background-color:#222;
position: relative;
height: 500px;
}
#child {
background-color:#444;
position: absolute;
bottom: 0px;
width: 100px;
height: 200px;
}
What do I need to do it achieve what I am trying to do? I could forgo the absolute/relative CSS rules and simply create a table within the parent DIV which would allow me to achieve both bottom alignment and content that dictates the parent's dimensions.
However, I'd like to know if there a way to do this in CSS and without having to set the width of the parent DIV.
thanks in advance!
The short answer is that what you are asking basically can't be done with pure CSS / HTML. (at least without tables) You'd need Javascript that would read #child's width/height and then do the calculation you want to do (I don't know) and set a new height/width to #parent.
Otherwise, if you mean that you want #child's height/width to change according to its content, of course this is native CSS, just set it's height/width to auto and then start adding text inside it you'll see it will start growing to fit your content inside.
As the #child is positioned absolute, then it is taken OUT of the normal flow of the document, therefore it will not affect the #parent.
With modern CSS, this is doable.
HTML:
<div id="parent">
<h3>Top Aligned Title</h3>
<div id="child">
<p>CHILD ELEMENT</p>
</div>
</div>
CSS:
#parent {
background:red;
height: 500px;
position:relative;
}
#child {
background:green;
position: absolute;
top:100%;
-webkit-transform: translateY(-100%);
-ms-transform: translateY(-100%);
transform: translateY(-100%);
width: 100px;
}
http://jsfiddle.net/Bushwazi/bpe5s6x3/
transform:translateY(-100%); is the trick. It's math is based on the element's box-model.
You could also combine top:50%; with transform:translateY(-50%); to center it.
You can swap top for left and translateY for translateX to position the element horizontally.
Here you go
HTML:
<main id="parent">
<div class="popup">Top Aligned Title
<div class="content">
Content
</div>
</div>
</main>
CSS:
#parent {
width: 120px;
}
.popup {
position: relative;
margin-top: 48px;
}
.content {
left: 0;
position: absolute;
background: green;
width: 100%;
}
http://jsfiddle.net/8L9votay/
You can play around with flex and zero-width/height.
I've recently come up with the following solution (for width):
#parent {
display: inline-flex;
flex-direction: column;
background: #518cff;
color: #fff;
}
#child-wrapper {
height: 0; /* This can also be max-height, but height is just enough */
}
#child {
transform: translateY(-100%); /* If you need to align child to the bottom */
background: #b40000;
color: #fff;
}
<div id="parent">
<h3>Top Aligned Title</h3>
<div id="child-wrapper"> <!-- This is the solution -->
<div id="child">
Child's content that is longer than parent's
</div>
</div>
</div>

Resources