This question already has answers here:
Html/Css Triangle with pseudo elements
(1 answer)
Speech bubble with arrow
(3 answers)
Closed 4 years ago.
I have a design requirement where a div has to overlap another div, but the text within the inner div needs to be visible.
<div class='box1'>
<div class='sendAbove'>
This is a message I want to be visible in this div
</div>
</div>
<div class='box2'>
</div>
CSS
.box1 {
width: 100px;
height: 100px;
position: absolute;
top: 20px;
left: 20px;
background: white;
border: solid red 1px;
z-index: 3;
}
.box2 {
width: 100px;
height: 100px;
position: absolute;
top: 50px;
left: 50px;
background: white;
border: solid blue 1px;
z-index: 4;
}
.sendAbove {
z-index: 5;
}
https://jsfiddle.net/sriv87/Lcoxrgpw/9/
Edit:
Updated fiddle
https://jsfiddle.net/sriv87/c8eh5fcs/
Ok, Edited as per your updated requirement. Check this.
.callout {
position: relative;
background: #ffffff;
border: 1px solid #f00;
width: 200px;
}
.callout:after,
.callout:before {
position: absolute;
left: 100%;
top: 50%;
border: solid transparent;
content: " ";
height: 0;
width: 0;
}
.callout:after {
border-color: rgba(255, 255, 255, 0);
border-left-color: white;
border-width: 10px;
margin-top: -10px;
}
.callout:before {
border-color: rgba(255, 0, 0, 0);
border-left-color: #f00;
border-width: 11px;
margin-top: -11px;
}
<div class="callout">
<p>Message here</p>
</div>
With your current layout it wont work. Because the parent of .sendAbove is absolute positioned, its html will allways be part of its parent. Regardless you make it absolute or relative.
So to make this workable, you should put the .sendAbove outside .box1. Give them both the same position, height and width.
.wrapper {
position: relative;
}
.box1, .sendAbove {
position: absolute;
top: 20px;
left: 20px;
width: 100px;
height: 100px;
}
.box1 {
background: white;
border: solid red 1px;
z-index: 3;
}
.box2 {
width: 100px;
height: 100px;
position: absolute;
top: 50px;
left: 50px;
background: white;
border: solid blue 1px;
z-index: 4;
}
.sendAbove {
z-index: 5;
}
<div class="wrapper">
<div class='box1'>
</div>
<div class='sendAbove'>
This is a message I want to be visible in this div
</div>
<div class='box2'>
</div>
</div>
Just change the background color settings in .box2 and that will make text underneath visible. How visible will be decided by the 'a' in rgba, and runs from 0 to 1, ie, 0.1 is very transparent, 0.9 has virtually no transparency.
.box2 {
width: 100px;
height: 100px;
position: absolute;
top: 50px;
left: 50px;
**background-color: rgba(255,255,255,0);**
border: solid blue 1px;
z-index: 4;
}
Related
Hi I have a question about my code.
Here is my problem.
I have two items and one frame. Frame has position relative a two items (children) have position absolute. They should be always on the same point inside my frame but when I am resizing the position of children are different in relation with frame. How to make the children always stay on same position for responzive design? Is it possible?
Try to change height of window in example too (not only width)
https://codesandbox.io/s/adoring-jackson-c6fth?file=/index.html:0-900
.frame {
width: 70vh;
height: 90vh;
border: 10px solid red;
margin: 10px auto;
position: relative;
}
.objA {
width: 130%;
position: absolute;
height: 40%;
bottom: -10%;
left: -20;
border: 2px solid green;
background: rgba(10, 101, 10, 0.7);
z-index: 2;
}
.objB {
width: 10%;
position: absolute;
height: 20%;
bottom: 20%;
left: 30%;
background: red;
z-index: 1;
}
<div class="frame"></div>
<div class="objA"></div>
<div class="objB"></div>
I post here my real example image for better imagination what the problem is.
All objects are positioned absolute (Waves, stars, robot etc...) Each wave should in every resized situation be in same position. Good to know is that every wave is separatly.
Make sure the positions and heights/widths are all in percents and most important: place your items inside the main <div class="frame"></div> element. You can start this way:
* {
box-sizing: border-box;
}
body {
background: none #014653;
margin: 0;
}
.frame {
width: 70vw;
height: 90vh;
border: 10px solid #5cb9b8;
background: none #5cb9b8;
margin: 5vh auto;
position: relative;
border-radius: 6px;
}
.frame-stage {
position: absolute;
top: 0;
right: 0;
bottom: 0;
left: 0;
border: 5px solid #a2cece;
background: none #014653;
border-radius: 5px;
}
.objA {
width: 10%;
position: absolute;
height: 20%;
bottom: 10%;
left: -20;
border: 2px solid green;
background: rgba(10, 101, 10, 0.7);
z-index: 2;
}
.objB {
width: 10%;
position: absolute;
height: 20%;
bottom: 30%;
left: 30%;
background: red;
z-index: 1;
}
<div class="frame">
<div class="frame-stage">
<div class="objA"></div>
<div class="objB"></div>
</div>
</div>
Updated codesandbox here.
How would I go about making this in CSS3/HTML5?
The Red background is the background of the div. The inner white is another div that will contain some text.
Since you already have 2 containers, you can use two pairs of pseudo elements for the corners, like this:
.outer {
width: 120px;
background: #a08;
position: relative;
padding: 30px;
}
.inner {
height: 118px;
background: #fff;
border: 1px dashed #a08;
flex: 1;
}
.outer::before, .outer::after, .inner::before, .inner::after {
content: '';
width: 20px;
height: 20px;
background: #a08;
background-clip: padding-box;
border: 1px dashed #a08;
border-radius: 50%;
position: absolute;
z-index: 1;
}
.outer::before {
top: 20px;
left: 20px;
}
.outer::after {
top: 20px;
right: 20px;
}
.inner::before {
bottom: 20px;
left: 20px;
}
.inner::after {
bottom: 20px;
right: 20px;
}
<div class="outer">
<div class="inner"></div>
</div>
I have two parent elements (a black and red divs). Each of them contain a child element. The black one contains a gray div. The red one contains a pink div.
Following constraints:
I can not change the relationship between child to it's own parent element, i.e. I can not move a child element outside of it's own parent element.
The red div has to remain underneath the black div
Is it possible to move the pink div above the gray div?
.parent-black {
width: 100%;
height: 50px;
background-color: rgba(0, 0, 0, .9);
color: white
}
.child-gray {
width: 250px;
height: 90px;
background-color: gray;
position: absolute;
right: 137px;
top: 20px;
z-index: 0;
color: white;
}
.parent-red {
width: 100%;
height: 40px;
background-color: red;
position: absolute;
top: 40px;
z-index: -999;
}
.child-pink {
width: 95%;
height: 80px;
background-color: pink;
top: 30px;
left: 20px;
position: absolute;
z-index: 9999;
}
<div class="parent-red">
2
<div class="child-pink">2.1</div>
</div>
<div class="parent-black">
1
<div class="child-gray">1.1</div>
</div>
Using jQuery below
$(document).ready(function() {
$('.child-gray').insertBefore($('.child-pink'));
})
.parent-black {
width: 100%;
height: 50px;
background-color: rgba(0, 0, 0, .9);
color: white
}
.child-gray {
width: 250px;
height: 90px;
background-color: gray;
position: absolute;
right: 137px;
top: 20px;
z-index: 0;
color: white;
}
.parent-red {
width: 100%;
height: 40px;
background-color: red;
position: absolute;
top: 40px;
z-index: -999;
}
.child-pink {
width: 95%;
height: 80px;
background-color: pink;
top: 30px;
left: 20px;
position: absolute;
z-index: 9999;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="parent-red">
2
<div class="child-pink">2.1</div>
</div>
<div class="parent-black">
1
<div class="child-gray">1.1</div>
</div>
Honestly, I don't get the real problem here... I guess this follows your constraints:
.parent-black {
width: 100%;
height: 50px;
background-color: rgba(0, 0, 0, .9);
color: white;
position: relative;
}
.child-gray {
width: 250px;
height: 90px;
background-color: gray;
position: absolute;
right: 137px;
top: 20px;
z-index: 0;
color: white;
}
.parent-red {
width: 100%;
height: 40px;
background-color: red;
margin-top: -20px;
}
.child-pink {
width: 95%;
height: 80px;
background-color: pink;
top: 70px;
left: 20px;
position: absolute;
z-index: 9999;
}
<div class="parent-black">
1
<div class="child-gray">1.1</div>
</div>
<div class="parent-red">
2
<div class="child-pink">2.1</div>
</div>
I'm wondering if this shape can be done in css3 with as little html as possible:
So far, I've managed to do this:
.wrapper {
position: relative;
}
.box {
width: 100px;
height: 100px;
border: 1px solid #000;
position: absolute;
top: 100px;
left: 100px;
}
.box:before {
content: "";
border: 1px solid #000;
border-bottom: 1px solid #fff;
width: 50%;
height: 10px;
position: absolute;
top: -12px;
left: -1px;
}
.box:after {
content: "";
border: 1px solid #000;
border-top: 1px solid #fff;
width: 50%;
height: 10px;
position: absolute;
bottom: -12px;
right: -1px;
}
<div class="wrapper">
<div class="box"></div>
</div>
The fiddle is here, but I don't know how to skew it like that so that I have right angled trapezoid on top and bottom.
The shape needs no extra elements
The shape can be created with just the <div>:
The left side is created with the divs left, top and bottom borders.
The right side is made by :before and its top, right and bottom borders
The spans joining the two boxes are created with the :after thanks to skewY
Note the browser support of the transform property. IE 9 requires the -ms- prefix, and Safari and the Android browser require -webkit-.
Working Example - just the shape
The CSS has been condensed and the border style of the pseudo elements is inherited from the div itself.
div {
border: solid 4px #000;
border-right-width: 0;
width: 100px;
height: 200px;
position: relative;
}
div:before,div:after {
content: '';
display: block;
height: 100%;
width: 100%;
border: inherit;
border-right-width: 4px;
border-left: none;
position: absolute;
left: 100%;
top: 13px;
margin-left: 20px;
}
div:after {
width: 20px;
border-right: none;
top: 5px;
transform: skewY(40deg);
margin: 0;
}
<div></div>
Working example - with text
With the example above, the contents will not be contained inside the entire shape. Rather, it will be constrained inside the divs half width. The contents needs to be wrapped in a <span> with 200% width to punch it outside of the divs constraints.
div {
border: solid 4px #000;
border-right-width: 0;
width: 100px;
height: 200px;
position: relative;
}
div:before,div:after {
content: '';
display: block;
height: 100%;
width: 100%;
border: inherit;
border-right-width: 4px;
border-left: none;
position: absolute;
left: 100%;
top: 13px;
margin-left: 20px;
}
div:after {
width: 20px;
border-right: none;
top: 5px;
transform: skewY(40deg);
margin: 0;
}
span {
width: 200%;
display: block;
padding: 20px 10px 10px;
}
<div><span>This is me writing a large amount of words into the div. I think that you may want a span in order to contain them.</span></div>
Using two different elements:
1) Separate the shape in two different rectangular
2)After use pseudo-elements after and before to create the connection line.
My approach:
.wrapper {
position: relative;
}
.box {
width: 50px;
height: 100px;
border: 4px solid #000;
position: absolute;
top: 100px;
left: 100px;
border-right: 0;
}
.box2 {
width: 50px;
height: 100px;
border: 4px solid #000;
position: absolute;
top: 112px;
left: 164px;
border-left: 0;
}
.box:after {
content: "";
position: absolute;
width: 15px;
border: 2px solid #000;
right: -15px;
top: 2px;
transform: rotate(45deg);
}
.box:before {
content: "";
position: absolute;
width: 15px;
border: 2px solid #000;
right: -15px;
bottom: -10px;
transform: rotate(45deg);
}
<div class="box"></div>
<div class="box2"></div>
I've used four divs: .left, .right, .middle-top and .middle-bottom; and skewed .middle-top and .middle-bottom to add those connection lines.
.left {
width: 40px;
height: 100px;
border: 3px solid black;
border-right: 1px solid white;
position: absolute;
top: 50px;
left: 100px;
}
.right {
width: 40px;
height: 100px;
border: 3px solid #000;
border-left: 1px solid white;
position: absolute;
top: 60px;
left: 160px;
}
.middle-top {
width: 20px;
height: 20px;
border-top: 3px solid black;
position: absolute;
transform: matrix(1, 0.5, -0.5, 1, 0, 0);
top: 55px;
left: 137px;
z-index: 9;
}
.middle-bottom {
width: 21px;
height: 20px;
border-top: 3px solid black;
position: absolute;
transform: matrix(1, 0.5, -0.5, 1, 0, 0);
top: 158px;
left: 135px;
z-index: 9;
}
<div class="left"></div>
<div class="middle-top"></div>
<div class="middle-bottom"></div>
<div class="right"></div>
Right, I ran into a bit of a problem and not to sure if this can be solved another way.
I need to move the content: "F"; and center it onto the border I have in the top left corner. Now is this possible without creating another element?
HTML:
<div class="userBoxF"></div>
CSS:
.userBoxF {
width: 200px;
height: 200px;
background: #eee;
border: 1px solid;
border-radius: 10px;
position: relative;
overflow: hidden;
}
.userBoxF:after {
content: "F";
position: absolute;
top: 0;
left: 0;
width: 0;
height: 0;
border: 40px solid #F385FF;
border-right-color: transparent;
border-bottom-color: transparent;
font-size: 30px;
}
The only way I can think to do it is to create the corner as a completely separate element so I can put the text "F" into a span (or something) and move it that way.
Demo Here
Note: Nothing here will change size, width and height for both the box and corner will always be the same.
Here is what I want, using the solution i found but would rather not use.
HTML:
<div class="userBoxF">
<div class="corner"><span>F</span></div>
</div>
CSS:
.userBoxF {
width: 200px;
height: 200px;
background: #eee;
border: 1px solid;
border-radius: 10px;
position: relative;
overflow: hidden;
}
.userBoxF .corner {
position: absolute;
top: 0;
left: 0;
width: 0;
height: 0;
border: 40px solid #F385FF;
border-right-color: transparent;
border-bottom-color: transparent;
font-size: 30px;
}
.userBoxF .corner span {
display: block;
position: absolute;
top: -30px;
left: -20px;
}
Here is a demo of the solution I came up with but I would rather not create anymore elements.
My Solution
You can use :before wit :after together.
I removed the span:
<div class="userBoxF">
</div>
And changed the CSS blocks to this:
.userBoxF:before {
position: absolute;
top: 0;
left: 0;
width: 0;
height: 0;
border: 40px solid #F385FF;
border-right-color: transparent;
border-bottom-color: transparent;
content: "";
}
.userBoxF:after {
display: block;
position: absolute;
top: 10px;
left: 14px;
content: "F";
font-size: 30px;
}
And here's the updated fiddle
EDIT: Here's an added bonus!
You can jack the "F" from the class, if you want it to be more versatile, if you use CSS's attr inside content. Example:
<div class="userBox" data-l="F">
</div>
And:
.userBox:after {
display: block;
position: absolute;
top: 10px;
left: 14px;
content: "" attr(data-l);
font-size: 30px;
}
And another fiddle
Arguably the "F" is actual content as it's not a styling option...it actually denotes something and, perhaps should be read by a screenreader (for instance) then a span with a gradient (TL - BR) mightbe more appropriate.
JSFiddle Demo
HTML
<div class="userBoxF">
<span class="section-letter">F</span>
</div>
CSS
.userBoxF {
width: 200px;
height: 200px;
background: #eee;
border: 1px solid;
border-radius: 10px;
position: relative;
overflow: hidden;
}
.section-letter {
position: absolute;
top: 0;
left: 0;
width:2em;
height:2em;
line-height: 1em;
text-align: left;
padding:0.25em 0 0 0.25em;
font-size: 30px;
background: linear-gradient(135deg, pink 0%, pink 50%, transparent 50%, transparent 100%);
}
Simply use another :psuedo:
Demo Fiddle
.userBoxF {
width: 200px;
height: 200px;
background: #eee;
border: 1px solid;
border-radius: 10px;
position: relative;
overflow: hidden;
}
.userBoxF:before,.userBoxF:after{
position: absolute;
top: 0;
left: 0;
}
.userBoxF:before {
content:"";
border: 40px solid #F385FF;
border-right-color: transparent;
border-bottom-color: transparent;
}
.userBoxF:after {
content:attr(data-l);
top: 10px;
left: 10px;
font-size: 30px;
}
From a single pseudo, you can use a gradient as background : DEMO
.userBoxF {
width: 200px;
height: 200px;
background: #eee;
border: 1px solid;
border-radius: 10px;
position: relative;
overflow: hidden;
}
.userBoxF:after {
content:"F";
position: absolute;
top: 0;
left: 0;
text-indent:20px;
line-height:60px;
width:80px;
height:80px;
background:linear-gradient(to bottom right, #F385FF 51%, transparent 49%);
font-size: 30px;
}
background-image as gradient can be just an image like in old days :
DEMO: