I'm toying around with a triangle inside a div and want to place text inside that triangle. So far everything works as expected - only problem is the text gets warped at space - if there is no space between the words it all fits:
<div style="position:absolute;z-index: 1;width: 0;height: 0;border-style: solid;border-width: 125px 125px 0 0;border-color: #1abc9c transparent transparent transparent;">
<div style="top: -100px; left: 10px; right:0px; position:absolute;">
<p>11 one</p>
</div>
</div>
I've tried making the text 1px and it still warps so it's obviously not a lack of space issue. Any ideas what's the problem?
Why is this happening?
Firstly, let's clean up the HTML by separating the CSS.
The HTML
<div class="outerParent">
<div class="innerParent">
<p>11 one</p>
</div>
</div>
The CSS
.outerParent {
position: absolute;
z-index: 1;
width: 0;
height: 0;
border-style: solid;
border-width: 125px 125px 0 0;
border-color: #1abc9c transparent transparent transparent;
}
.innerParent {
top: -100px;
left: 10px;
right: 0px;
position: absolute;
}
Better! Now, the first thing we see is that .outerParent has width: 0. This means that it's child .innerParent has no width. When text hits the edge of its container (which happens immediately because of width: 0 on .outerParent), it will wrap any whitespace, and this is controlled by the white-space property:
The white-space CSS property is used to to describe how white spaces inside the element is handled.
How do I prevent this from happening?
The default white-space value is "normal" and this will wrap. Use the white-space property and set it to "nowrap":
white-space: nowrap;
The other option is to force the paragraph element to push outside of it's parent by giving it a width:
width: 50px;
Working Example
.outerParent {
position: absolute;
z-index: 1;
width: 0;
height: 0;
border-style: solid;
border-width: 125px 125px 0 0;
border-color: #1abc9c transparent transparent transparent;
}
.innerParent {
top: -100px;
left: 10px;
right: 0px;
position: absolute;
}
p {
white-space: nowrap;
}
<div class="outerParent">
<div class="innerParent">
<p>11 one</p>
</div>
</div>
Related
I'd like to set a margin all around a <div> with a position:absolute inside a scrollable <div> to let some free space between the inside div and the scrollable area boundaries (right and bottom).
I tried something like this but with no luck:
<div style="overflow:scroll">
<div style="position:absolute; margin-right:100px; margin-bottom:100px">DRAG ME</div>
</div>
Demo here: https://jsfiddle.net/ayft01x0/
Only the margin-bottom works, and only in Chrome.
You can also imagine that there are other elements inside the scollable div and that they should stay clickable even if they are masked by the margin of the "drag me" element (which should be the case when using CSS margins).
I'm looking preferably for a CSS-only solution that works in Webkit browsers.
Any ideas?
Absolute positioning changes the way margins work, but you can get the effect you're after with borders:
We add a border to the left and the right. This interferes with the border you already had on the draggable element, so we add a pseudoelement to take care of the design. The pseudoelement covers up the "drag me" text, so we add a wrapper around that content and fix the z indices
Here's an update to your fiddle, and here's a snippet of the essential css
#container {
position: relative;
width: 200px;
height: 200px;
border: solid 1px black;
background-color: white;
}
#box {
position: absolute;
border-right: 100px solid transparent; /* changed this */
border-bottom: 100px solid transparent; /* changed this */
outline: 1px solid red; /* just for demo purposes */
width: 80px;
height: 80px;
left: 50px;
top: 50px;
/* dropped the border and background styles */
}
#box span { /* added this element */
position: relative;
z-index: 1;
}
#box:before { /* added this element */
content: '';
position: absolute;
z-index: 0;
width: 80px;
height: 80px;
/* placement adjusted to take the border into account */
left: -2px;
top: -2px;
/* border and background styles moved from #box to here */
border: solid 2px #666;
border-radius: 10px;
background: #ccc; /* shaved off a couple bytes by dropping the -color */
}
<div id="container" style="overflow:scroll">
<div id="box">
<span>DRAG ME</span><!-- added this wrapping element so that it can get a z-index -->
</div>
</div>
Note that I've kept your initial positions for the draggable box, but I would probably actually do it like this. The negative margins are just half the element's dimensions. This way if you tweak the size of #container you don't have to recalculate #box's starting position
#box {
...
width: 80px;
height: 80px;
left: 50%;
top: 50%;
margin-left: -40px;
margin-top: -40px;
}
There is a workaround by using an encapsulating div with inner padding and make it transparent to the mouse interactions using the pointer-events property.
<div style="overflow:scroll">
<div style="position:absolute; padding-right:100px; padding-bottom:100px; pointer-events:none">
<div style="pointer-events:all">DRAG ME</div>
</div>
</div>
Demo here: https://jsfiddle.net/1axtonez/
The easiest way to achieve this is to create an invisible CSS ::before pseudo-element that covers the box plus a padding, and to make it transparent to the mouse interactions using the pointer-events property:
div.box::before{
content: '';
position: absolute;
left: 0;
top: 0;
width: 100%;
height: 100%;
padding-right: 100px;
padding-bottom: 100px;
pointer-events: none;
/* background-color: rgba(255,0,0,0.2); // to understand what is going on */
}
Demo here: https://jsfiddle.net/rmxwwyno/
Be warned that it's not working when the box has an overflow property that is not set to visible.
Similar to these, but with a separate border. I asked this question earlier, but didn't realize there were other methods besides using linear gradients.
Examples: http://i.imgur.com/TqVR67J.png
It's not pure CSS (and probably not exactly what you're looking for), but you could just do a larger element first that just forms the border, and then have a smaller sibling element with offset afterwards:
<div id="background"></div>
<div id="foreground"></div>
and then the css:
#background{
position: absolute;
}
#foreground{
position: relative;
top: 5px;
left: 5px;
}
(Obviously, you would have to add all of the styling and extra tags for the beveling.)
Take a look at this fiddle. This might gave you an idea of how to create it with css.
Beveled border with css
HTML
<div class='box'>
<img src="http://placehold.it/350x150" />
<img class='cart' src="http://www.rotweinelang.at/themes/wein/img/elements/smallShoppingCartIcon.png" />
</div>
CSS
.box {
width: 350px;
position: relative;
}
.box::after {
content: "";
position: absolute;
top: 0;
right: -2px;
border-style: solid;
border-width: 0 40px 40px 0;
border-color: transparent #fff transparent transparent;
}
.cart {
position: absolute;
top: 0;
right: -4px;
z-index: 1;
}
I found various examples of how to create triangles using CSS (like this one); all of them are based on creating a 0-sized box and fiddling with borders to create the triangle shape. Ok, very nice.
But how can I actually place something inside such a triangle?
You can use positioning techniques to place some content over the triangle and not under the triangle..
I emphasized over and under because using positioning am positioning the text over the triangle, so triangle element isn't the parent of the content, as to create triangles we use height: 0; and width: 0; so you need to overlay the text.
Just make sure you use position: relative; for parent element holding absolute positioned element.
Didn't used z-index but you can use that to play safe with the stacking order.
Demo
<div class="wrap">
<div class="triangle"></div>
<span>Hello</span>
</div>
div.wrap {
position: relative;
}
div.triangle {
height: 0;
width: 0;
border: 50px solid #f00;
border-top-color: transparent;
border-left-color: transparent;
border-right-color: transparent;
}
div span {
position: absolute;
left: 35px;
bottom: 0;
}
This way can be sloppy but it would work for a basic situation.
http://jsfiddle.net/Yc5nF/1/
<div class="arrow-right">
<p>Foobar</p>
</div>
.arrow-right {
position: relative;
width: 0;
height: 0;
border-left: 150px solid transparent;
border-bottom: 150px solid green;
border-right: 150px solid transparent;
}
.arrow-right p {
position: absolute;
top: 70px;
left: -20px;
}
Please see this fiddle, or the code below:
http://jsfiddle.net/MegaMatt3/92G6X/9/
HTML:
<div id="outer">
<div id="inner"></div>
</div>
CSS:
#outer {
border: 1px solid black;
box-shadow: 0 0 20px rgba(0, 0, 0, 1) inset;
height: 200px;
position: relative;
width: 200px;
}
#inner {
background-color: #55A8FF;
bottom: 0;
height: 50px;
left: 0;
position: absolute;
width: 100%;
}
If I have a parent element, with an inset box shadow, and a child element inside it, the child element appears over top of the box shadow. I'd like for the child element to be "underneath" the box shadow, if possible. The effect would essentially show the inset box shadow on top of the child element.
I've messed with the z-index, but with no luck. Is this possible? Any help would be much appreciated. Thanks.
EDIT:
This question is kind of a mess now, but my original question should have indicated that I'm looking for a solution that works when the outer div has a non-transparent background. I've updated my original fiddle and code to reflect this scenario. The other answers here are valid, but the one I've marked as correct works for me in that scenario.
Another solution that works with non transparent backgrounds:
Set the shadow on a pseudo element
CSS
#outer {
border: 1px solid black;
height: 200px;
position: relative;
width: 200px;
background-color: white;
}
#outer:after {
content: "";
box-shadow: 0 0 10px rgba(0, 0, 0, 0.5) inset;
height: 100%;
position: absolute;
width: 100%;
left: 0px;
top: 0px;
}
#inner {
background-color: #55A8FF;
bottom: 0;
height: 50px;
left: 0;
position: absolute;
width: 100%;
}
demo
Set #inner to a negative z-index.
#inner {
background-color: #55A8FF;
bottom: 0;
height: 50px;
left: 0;
position: absolute;
width: 100%;
z-index: -10;
}
http://jsfiddle.net/S8Sm7/
PS:
Remember to close your tags :) just to be safe.
I would add another <div>.
You could use z-index, but if anything else is in the <div> you're going to have modify them all or do some other hack.
I suggest adding another <div> with the shadow. This is a flexible solution.
<div id="outer">
<div id="inner"></div>
<div id="newDiv"></div> // shadow moved to this div
</div>
I had a similar problem here css - box shadow covering all contained divs using absolute positioning
example here: http://jsfiddle.net/92G6X/8/
Through help on stackoverflow I've been able to generate and position a CSS triangle in the correct position on my website, I've also learnt how to color a triangle in 2 equal halves.
But I am stuck on merging the two examples together, what I've tried I don't think is worth pasting here due to the mess I've made of it.
I am trying to get a triangle that has the proportions and sits at the bottom of the div like this fiddle example and then is split in 2 colors like this fiddle example.
Where I believe I am going wrong is that in the different fiddles there are different uses of:
:before
Well..., Here is my attempt to achieve this effect (proportions + split in 2 colors):
JSFiddle Demo.
In this demo, I added the triangle to the .bottom div and positioned that to stay at the top (with a negative value).
Then added margin-top: 1%; property to move the triangle when resizing the window:
HTML
<div class="top"></div>
<div class="bottom">
<div class="triangle"></div>
</div>
CSS:
.top {
/* other styles... */
position: relative;
z-index: 2;
}
.bottom {
background: lightGreen;
height: 100px;
position: relative;
z-index: 1; /* A lower z-index value than .top */
/* Or use overflow: hidden; instead */
}
.triangle {
width: 40px;
height: 20px;
position: absolute;
left: 0;
right: 0;
top: -20px;
margin: auto;
margin-top: 1%; /* Move the triangle when resizing the window */
z-index: 1;
}
.triangle:before {
content: " ";
position: absolute;
width: 0;
height: 0;
border-style: solid;
border-width: 0 20px 20px 0;
border-color: transparent blue transparent transparent;
}
.triangle:after {
content: " ";
position: absolute;
left: 20px;
width: 0;
height: 0;
border-style: solid;
border-width: 20px 20px 0 0;
border-color: red transparent transparent transparent;
}