I am trying to create a ribbon at the beginning of a rectangle. However, I cannot figure out how to make it appear BEHIND the rectangle.
Please see this codepen: http://codepen.io/gosusheep/pen/aOqOBy
The part for creating the ribbon and putting it behind the rectangle is here:
.rectangle::before{
content: "";
width: 0;
height: 0;
display: block;
position: absolute;
z-index: -1;
border-left: 25px solid transparent;
border-right: 25px solid $blue;
border-top: 25px solid $blue;
border-bottom: 25px solid $blue;
left: -30px;
top: 10%;
}
Even with position: absolute, and z-index: -1, it appears ON TOP of the div.
Can anyone help with this?
What is happening here is that apparently, the property transform: translateX(-50%); it's "overriding" in some way the z-index. My solution is just center rectangle otherwise, for example:
.rectangle{
margin: 0 auto;
}
DEMO
The reason for your problem is not because children cannot be positioned behind their parent but because you are using a transform on the parent. Using transforms affect the stacking context like mentioned in this answer by BoltClock.
One solution would be to avoid the transform totally and use left: calc(50% - 100px) instead to position the ribbon at the center (like in the below snippet). (50% - 100px) is used as the value because 100px is half of the box width (50% is the center point of the parent).
.rectangle {
width: 200px;
height: 50px;
background-color: #8080ff;
position: relative;
left: calc(50% - 100px); /* newly added */
border: 1px #6666ff solid;
}
ul {
list-style: none;
}
li {
display: inline;
}
li + li::before {
content: " | ";
}
.container {
width: 100%;
position: relative;
}
.rectangle {
width: 200px;
height: 50px;
background-color: #8080ff;
position: relative;
left: calc(50% - 100px); /* newly added */
border: 1px #6666ff solid;
}
.rectangle::before {
content: "";
width: 0;
height: 0;
display: block;
position: absolute;
z-index: -1;
border-left: 25px solid transparent;
border-right: 25px solid #8080ff;
border-top: 25px solid #8080ff;
border-bottom: 25px solid #8080ff;
left: -30px;
top: 10%;
}
<p>put a pipe between nav elements</p>
<nav>
<ul>
<li>banana</li>
<li>woof</li>
<li>quack</li>
</ul>
</nav>
<p>Ribbon on the end of a rectangle</p>
<div class='container'>
<div class='rectangle'></div>
</div>
If in case you can't use the above solution, then you could follow the approach described below.
Assuming you don't have any other use for the ::after pseudo-element, you could use that to create the rectangle and give it a z-index higher than the ::before pseudo-element to make it appear behind the rectangle.
/* Modified */
.rectangle {
width: 200px;
height: 50px;
position: relative;
left: 50%;
transform: translateX(-50%);
}
/* Added */
.rectangle::after {
content: "";
width: 100%;
height: 100%;
top: 0px;
left: 0px;
display: block;
position: absolute;
background-color: #8080ff;
border: 1px #6666ff solid;
z-index: -1;
}
.rectangle{
padding: 4px;
box-sizing: border-box;
}
Below is a sample snippet:
ul {
list-style: none;
}
li {
display: inline;
}
li + li::before {
content: " | ";
}
.container {
width: 100%;
position: relative;
}
.rectangle::before {
content: "";
width: 0;
height: 0;
display: block;
position: absolute;
z-index: -2;
border-left: 25px solid transparent;
border-right: 25px solid #8080ff;
border-top: 25px solid #8080ff;
border-bottom: 25px solid #8080ff;
left: -30px;
top: 10%;
}
/* Modified */
.rectangle {
width: 200px;
height: 50px;
position: relative;
left: 50%;
transform: translateX(-50%);
}
/* Added */
.rectangle::after {
content: "";
width: 100%;
height: 100%;
top: 0px;
left: 0px;
display: block;
position: absolute;
background-color: #8080ff;
border: 1px #6666ff solid;
z-index: -1;
}
.rectangle{
padding: 4px;
box-sizing: border-box;
}
<p>put a pipe between nav elements</p>
<nav>
<ul>
<li>banana</li>
<li>woof</li>
<li>quack</li>
</ul>
</nav>
<p>Ribbon on the end of a rectangle</p>
<div class='container'>
<div class='rectangle'>
Some content
</div>
</div>
Solution here, look closely at z-indexes and positions
.container{
position: relative;
width: 100%;
z-index: 1;
}
.rectangle{
width: 200px;
height: 50px;
background-color: $blue;
position: absolute;
left: 50%;
border: 1px darken($blue,5%) solid;
}
.rectangle::after{
content: "";
width: 0;
height: 0;
border-left: 25px solid transparent;
border-right: 25px solid $blue;
border-top: 25px solid $blue;
border-bottom: 25px solid $blue;
left: -30px;
top: 10px;
position: absolute;
z-index: -1;
}
And your codepen edited http://codepen.io/anon/pen/mJXeed working now
Related
I am building a testimonial component in react and I have to make a shape direction towards pic, I have done the shape exactly how I want but the testimonial div has border color when I apply the div gets a border but the shape is left outside I have tried several ways but couldn't find a solution, I have attached the picture of what I want and how it is right now.
How I want it
What I have achieved till now
Below is my CSS
#page {
background-color: lightgray;
padding: 40px;
}
.container {
position: relative;
background-color: #FFFFFF;
max-width: 600px;
height: auto;
border: 1px solid #E7E7E7;
padding: 30px;
box-sizing: border-box;
}
.container:after {
position: absolute;
width: 0;
height: 0;
border-top: 50px solid white;
border-right: 40px solid transparent;
top:101%;
left: 40%;
content: '';
transform: rotate(14deg);
margin-top: -10px;
}
<div id="page">
<div class="container">This is a test</div>
</div>
You may use a filter , choice: drop-shadow.
support ? , don't be afraid : https://caniuse.com/?search=drop-shadow All but IE 6-11 and Opera mini
here is an exemple to run:
#page {
background-color: lightgray;
padding: 40px;
}
.container {
position: relative;
background-color: #FFFFFF;
max-width: 600px;
height: auto;
filter:
/* draw borders without blur*/
drop-shadow(0 1px )
drop-shadow(1px 0px )
drop-shadow(0 -1px )
drop-shadow(-1px 0px )
/* add eventually a shadow */
drop-shadow(0 0 3px )
/*and another for demo purpose */
drop-shadow(30px 30px 3px gray );
padding: 30px;
box-sizing: border-box;
}
.container:after {
position: absolute;
width: 0;
height: 0;
border-top: 50px solid white;
border-right: 40px solid transparent;
top:101%;
left: 40%;
content: '';
transform: rotate(14deg);
margin-top: -10px;
}
<div id="page">
<div class="container">This is a test</div>
</div>
You can use a :before that's 1px bigger than your :after which uses the border colour instead and then it will be mostly covered by the :after, giving you your "fake" border. Just makes sure your z-indexing is correct so it doesn't show inside your bubble.
EDIT: Adding in example css.
I modified some colours and spacing for illustrative purposes:
#page {
background: #ffc;
padding: 40px 40px 60px;
position: relative;
z-index: 0;
}
.container {
position: relative;
background: #fff;
max-width: 600px;
height: auto;
border: 1px solid #000;
padding: 30px;
box-sizing: border-box;
}
.container:after,
.container:before {
position: absolute;
width: 0;
height: 0;
top: 101%;
left: 40%;
content: "";
transform: rotate(14deg);
margin-top: -10px;
}
.container:after {
border-top: 50px solid #fff;
border-right: 40px solid transparent;
}
.container:before {
border-top: 52px solid #000;
border-right: 42px solid transparent;
margin-left: -1px;
z-index: -1;
}
<div id="page">
<div class="container">This is a test</div>
</div>
Adding both a :before and :after is a good idea to get the effect you want. Using a CSS box-shadow or outline won't work because it actually renders a complete square around your arrow/triangle shape. A z-index is added to the before to push it to the background. In that way it's not overlapping the other objects.
Here's an example of what you might want. You can adjust the border sizes to finetune it.
.container {
position: relative;
background-color: #FFFFFF;
max-width: 600px;
height: auto;
border: 1px solid #E7E7E7;
padding: 30px;
box-sizing: border-box;
}
.container:before {
position: absolute;
width: 0;
height: 0;
border-top: 53px solid #e7e7e7;
border-right: 43px solid transparent;
top: 100%;
left: 40%;
content: '';
transform: rotate(14deg);
margin-top: -10px;
z-index: -1;
}
.container:after {
position: absolute;
width: 0;
height: 0;
border-top: 50px solid white;
border-right: 40px solid transparent;
top:101%;
left: 40%;
content: '';
transform: rotate(14deg);
margin-top: -10px;
}
<div class="container"></div>
I am trying to make slanted box shadow on both sides of a div, which I have added here as an image.
The red part is indicating here shadow. actually color is not solid, it should gradually decrease when it is moving to outside from border.
Here is my contribution hope it gives you a baseline.
.box {
width: 150px;
height: 200px;
position: relative;
padding-left: 25px;
padding-right: 25px;
}
.box-content {
display: flex;
align-items: center;
justify-content: center;
z-index: 2;
background-color: white;
border: 2px solid black;
width: 100%;
height: 100%;
position: relative;
}
.box::before {
content: '';
display: block;
border-top: 0;
border-bottom: 180px solid transparent;
border-right: 25px solid red;
position: absolute;
left: 0;
bottom: 0;
}
.box::after {
content: '';
display: block;
border-top: 0;
border-bottom: 180px solid transparent;
border-left: 25px solid red;
position: absolute;
right: -4px;
bottom: 0;
}
<div class="box">
<div class="box-content">
Box
</div>
</div>
Try this:
div{
width: 200px;
height: 200px;
border:1px solid black;
background: white;
}
div:before{
content:' ';
display:block;
width: 200px;
height:200px;
background: linear-gradient(transparent, black);
position: fixed;
transform: matrix3d(1.1,0,0.00,0,0.00,0.71,0.71,0.0007,0,-0.71,0.71,0,0,37,0,1); z-index: -1;
}
<div>Hello</div>
Using transform: skew() applied to the div's before and after
jsFiddle 1
code:
#test {
width: 150px;
height: 220px;
line-height: 220px;
background-color: white;
border: 2px black solid;
text-align: center;
position: relative;
margin: 10px 150px;
}
#test:before, #test:after {
width: 150px;
height: 200px;
position: absolute;
bottom: 0;
left: -11px;
z-index: -1;
content: " ";
display: block;
background-color: red;
transform: skew(5deg, 0);
}
#test:after {
transform: skew(-5deg, 0);
left: 11px;
}
<div id="test">Box</div>
EDIT : to give the shadow effect some real blur with gradient and transparency, we could make use of linear-gradient background with two rgba() values, as well as CSS blur() (1) filter.
jsFiddle 2
code:
#test {
width: 150px;
height: 220px;
line-height: 220px;
background-color: white;
border: 2px black solid;
text-align: center;
position: relative;
margin: 10px 150px;
}
#test:before, #test:after {
width: 150px;
height: 200px;
position: absolute;
bottom: 0;
left: -11px;
z-index: -1;
content: " ";
display: block;
background: linear-gradient(rgba(0, 0, 0, 0.5), rgba(0, 0, 0, 0.7));
transform: skew(5deg, 0);
filter: blur(2px);
}
#test:after {
transform: skew(-5deg, 0);
left: 11px;
}
<div id="test">Box</div>
Notes:
(1) browser support for CSS filter
I was trying to customize ionic lists and tabs but since I am not too experienced in css does anyone know how to get these layouts ? :
List picture:
TABS picture:
You could use a border trick with some pseudo elements for this:
.onecorner,
.twocorners {
height: 50px;
width: 300px;
line-height: 50px;
text-align: center;
background: lightgray;
margin-left: 25px;
margin-right: 25px;
position: relative;
}
.onecorner:after{
content: "";
position: absolute;
top: 0;
left: 100%;
height:100%;
width:25px;
background:inherit;
}
.onecorner:before,
.twocorners:before {
content: "";
position: absolute;
top: 0;
left: 0;
transform: translateX(-100%);
width: 0;
height: 25px;
border-top: 25px solid transparent;
border-right: 25px solid lightgray;
}
.twocorners:after {
content: "";
position: absolute;
top: 0;
right: 0;
transform: translateX(100%);
width: 0;
height: 25px;
border-bottom: 25px solid transparent;
border-left: 25px solid lightgray;
}
<div class="onecorner">tab 1</div>
<br/>
<div class="twocorners">tab 2</div>
Check this link. I want to position the blue and black div exactly at the right and bottom of the red div respectively. I want the right vertex of the blue div to align with the right vertex of the red one and the bottom vertex of the black div to align with the bottom vertex of the red one. What is the best way to do that?
Thank You in advance.
The HTML
<div id="diamond">
<div id="diamond_right"></div>
<div id="diamond_bottom"></div>
</div>
The CSS
#diamond {
width: 0;
height: 0;
border: 300px solid transparent;
border-bottom-color: red;
position: relative;
top: -300px;
z-index:0;
}
#diamond:after {
content: '';
position: absolute;
left: -300px;
top: 300px;
width: 0;
height: 0;
border: 300px solid transparent;
border-top-color: red;
}
#diamond_right {
width: 0;
height: 0;
border: 50px solid transparent;
border-bottom-color: blue;
position: relative;
top: -50px;
z-index:1;
}
#diamond_right:after {
content: '';
position: absolute;
left: -50px;
top: 50px;
width: 0;
height: 0;
border: 50px solid transparent;
border-top-color: blue;
}
#diamond_bottom {
width: 0;
height: 0;
border: 50px solid transparent;
border-bottom-color: black;
position: relative;
top: -50px;
z-index:2;
}
#diamond_bottom:after {
content: '';
position: absolute;
left: -50px;
top: 50px;
width: 0;
height: 0;
border: 50px solid transparent;
border-top-color: black;
}
Much easier to do this with a single normal div and a couple of pseudo elements using standard techniques and then rotate the whole lot together.
#diamond {
width: 300px;
height: 300px;
background: red;
position: relative;
margin: 75px;
transform: rotate(-45deg);
}
#diamond::before,
#diamond::after {
content: '';
width: 50px;
height: 50px;
bottom: 0;
position: absolute;
}
#diamond::before {
background: blue;
right: 0;
}
#diamond::after {
background: black;
left: 0;
}
<div id="diamond"></div>
I did this with the blue one in your fiddle and it aligned with the right vertex, if you plug this in is this what you were looking to achieve?
#diamond_right {
width: 0;
height: 0;
border: 50px solid transparent;
border-bottom-color: blue;
position: absolute;
top: 200px;
right: -300px;
z-index:1;
}
#diamond_right:after {
content: '';
position: absolute;
left: -50px;
top: 50px;
width: 0;
height: 0;
border: 50px solid transparent;
border-top-color: blue;
}
I recently came across an article detailing how to create responsive triangles with pure CSS. I was wanting to take this a step further to incorporate it into a current design.
I was able to get four triangles placed within a square div perfectly (creating an origami-type effect) and they are responsive.
However when I try to incorporate a hover effect, it does not change the color of the triangle - only the empty space around it.
Also, when my square's width changes (keeping with the responsiveness) the bottom triangle separates from the others - because I used absolute positioning and bottom: 0; to place the triangles within the square.
Does anyone know a way around this to achieve my desired effect in pure CSS? Here is the relevant code : JSFiddle
HTML:
<body>
<div class="container">
<div class="box">
<div class="triSectionTop"></div>
<div class="triSectionRight"></div>
<div class="triSectionBottom"></div>
<div class="triSectionLeft"></div>
</div>
</div>
</body>
SCSS:
.container {
box-sizing: border-box;
height: 400px;
width: 400px;
}
.box {
position: relative;
box-sizing: border-box;
height: 400px;
width: 100%;
}
.triSectionTop {
position: absolute;
top: 0;
width: 100%;
height: 0;
padding-left: 50%;
padding-top: 50%;
overflow: hidden;
&:after {
content: "";
display: block;
width: 0;
height: 0;
margin-left: -200px;
margin-top: -200px;
border-left: 200px solid transparent;
border-right: 200px solid transparent;
border-top: 200px solid #41a5e8;
}
}
.triSectionRight {
position: absolute;
right: 0;
width: 50%;
height: 0;
padding-top: 50%;
padding-bottom: 50%;
overflow: hidden;
&:after {
content: "";
display: block;
width: 0;
height: 0;
margin-top: -200px;
border-top: 200px solid transparent;
border-bottom: 200px solid transparent;
border-right: 200px solid #4eb2f5;
}
}
.triSectionBottom {
position: absolute;
bottom: 0;
width: 100%;
height: 0;
padding-left: 50%;
padding-bottom: 50%;
overflow: hidden;
&:after {
content: "";
display: block;
width: 0;
height: 0;
margin-left: -200px;
border-left: 200px solid transparent;
border-right: 200px solid transparent;
border-bottom: 200px solid #5abeff;
}
}
.triSectionLeft {
position: absolute;
left: 0;
width: 0;
height: 0;
padding-top: 50%;
padding-bottom: 50%;
padding-left: 50%;
overflow: hidden;
&:after {
content: "";
display: block;
width: 0;
height: 0;
margin-top: -200px;
margin-left: -200px;
border-top: 200px solid transparent;
border-bottom: 200px solid transparent;
border-left: 200px solid #67cbff;
}
}
You can achieve the hover effect (background-color change and outside box-shadow) by making the triangles with transform-rotate.
This will allow you to triger the hover event only when the shape is actualy hovered :
DEMO
.box{
width:500px;
height:500px;
position:relative;
overflow:hidden;
}
.box > div{
position:absolute;
bottom:50%; left:50%;
width:75%; height:75%;
transform-origin:0 100%;
z-index:1;
}
.triSectionTop{
-webkit-transform:rotate(-45deg);
-ms-transform:rotate(-45deg);
transform:rotate(-45deg);
background:#41A5E8;
}
.triSectionRight{
-webkit-transform:rotate(45deg);
-ms-transform:rotate(45deg);
transform:rotate(45deg);
background:#4EB2F5;
}
.triSectionBottom{
-webkit-transform:rotate(135deg);
-ms-transform:rotate(135deg);
transform:rotate(135deg);
background:#5ABEFF;
}
.triSectionLeft{
-webkit-transform:rotate(225deg);
-ms-transform:rotate(225deg);
transform:rotate(225deg);
background:#67CBFF;
}
.box > div:hover{
background:teal;
box-shadow: 0 0 10px 0 #656565;
z-index:2;
}
<div class="box">
<div class="triSectionTop"></div>
<div class="triSectionRight"></div>
<div class="triSectionBottom"></div>
<div class="triSectionLeft"></div>
</div>
This will work try this
Here is the Html
<div class="arrow-up"></div>
<div class="arrow-down"></div>
<div class="arrow-left"></div>
<div class="arrow-right"></div>
Here is the CSS
.arrow-up {
width: 0;
height: 0;
border-left: 5px solid transparent;
border-right: 5px solid transparent;
border-bottom: 5px solid black;
}
.arrow-down {
width: 0;
height: 0;
border-left: 20px solid transparent;
border-right: 20px solid transparent;
border-top: 20px solid #f00;
}
.arrow-right {
width: 0;
height: 0;
border-top: 60px solid transparent;
border-bottom: 60px solid transparent;
border-left: 60px solid green;
}
.arrow-left {
width: 0;
height: 0;
border-top: 10px solid transparent;
border-bottom: 10px solid transparent;
border-right:10px solid blue;
}
here is the source