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>
Related
Is there a way to achieve this border in CSS? I've got one DIV with list of bullet points and I need to wrap it in a border like the image.
You can first create one element with border except border-bottom and then use :before and :after pseudo-elements to add triangle border at bottom.
div {
width: 200px;
height: 150px;
border: 1px solid black;
border-bottom: none;
position: relative;
background: white;
margin: 20px;
}
div:after, div:before {
content: '';
width: 0;
height: 0;
border-style: solid;
border-width: 50px 101px 0 101px;
border-color: black transparent transparent transparent;
top: 100%;
left: -1px;
position: absolute;
}
div:after {
border-color: white transparent transparent transparent;
top: calc(100% - 1px);
}
<div></div>
Have a look at this Fiddle
Basically add this css to a div:
#base {
background: red;
display: inline-block;
height: 55px;
margin-left: 20px;
margin-top: 55px;
position: relative;
width: 100px;
}
#base:after {
border-bottom: 35px solid red;
border-left: 50px solid transparent;
border-right: 50px solid transparent;
content: "";
height: 0;
left: 0;
position: absolute;
top: 54px;
width: 0;
-ms-transform: rotate(180deg);
-webkit-transform: rotate(180deg);
transform: rotate(180deg);
}
try this one:
.down-arrow {
display: inline-block;
position: relative;
background: darkcyan;
padding: 15px 0;
width: 200px;
text-align: center;
}
.down-arrow:after {
content: '';
display: block;
position: absolute;
left: 0;
top: 100%;
width: 0;
height: 0;
border-top: 20px solid darkcyan;
border-right: 100px solid transparent;
border-bottom: 0 solid transparent;
border-left: 100px solid transparent;
}
DEMO HERE
Here is the code for the box:
.box {
background: #fff;
border: 1px solid #000;
display: inline-block;
height: 55px;
margin-left: 20px;
margin-top: 55px;
position: relative;
width: 100px;
}
.box:after {
border-top: 35px solid #fff;
border-left: 50px solid transparent;
border-right: 50px solid transparent;
content: '';
height: 0;
left: 0;
position: absolute;
top: 55px;
width: 0;
}
.box:before {
border-top: 35px solid #000;
border-left: 50px solid transparent;
border-right: 50px solid transparent;
content: '';
height: 0;
left: 0;
position: absolute;
top: 56px;
width: 0;
}
<div class="box">
</div>
I hope it helps
I tried to add an arrow shape to a div. i managed to add it to the end of the div but i am struggling to figure out how to add it to the front as well without using a new class. Is it possible to achieve it with only one class?
edit: my answer to the question with a different shape approach,
i think they are all 3 very useful:
.arrow {
margin-left: 100px;
position: relative;
background: pink;
width: 400px;
height: 100px;
text-align:center;
line-height:100px;
margin-bottom:10px;
}
.arrow:after {
border: solid transparent;
content: " ";
position: absolute;
border-bottom-color: white;
border-width: 50px;
left: 0;
top: 0;
transform: rotate(90deg);
}
.arrow:before {
border: solid transparent;
content: " ";
position: absolute;
border-bottom-color: pink;
border-width: 50px;
left: 400px;
top: 0;
transform: rotate(90deg);
}
<div class="arrow">
1
</div>
<div class="arrow">
2
</div>
You will need an inner element. What that element is, is purely up to you. Here I've used a <span> to make the left arrow appear.
.arrow {
float: left;
width: 128px;
height: 50px;
background-color: white;
border: 1px solid green;
position: relative;
margin-right: 40px;
text-align: center;
border-left: none;
}
.arrow:after,.arrow span:after {
content: '';
position: absolute;
top: 0px;
left: 128px;
width: 0;
height: 0;
border: 25px solid transparent;
border-left: 12px solid white;
z-index: 2;
}
.arrow:before,.arrow span:before {
content: '';
position: absolute;
top: 0px;
left: 129px;
width: 0;
height: 0;
border: 25px solid transparent;
border-left: 12px solid green;
z-index: 1;
}
.arrow span:after {
left: 0;
}
.arrow span:before {
left: 1px;
}
<div class="arrow"><span></span>1</div>
<div class="arrow"><span></span>2</div>
<div class="arrow"><span></span>3</div>
<div class="arrow"><span></span>4</div>
<div class="arrow"><span></span>5</div>
I have modified chevron shape, from this page: https://css-tricks.com/examples/ShapesOfCSS/ (borrowed idea, credits to mr Anthony Ticknor:))
.chevron {
position: relative;
text-align: center;
height: 60px;
width: 260px;
line-height:60px;
margin-bottom:10px;
}
.chevron:before {
content: '';
position: absolute;
top: 0;
left: 3%;
height: 50%;
width: 100%;
transform: skew(25deg, 0deg);
border:1px solid red;
border-bottom:none;
}
.chevron:after {
content: '';
position: absolute;
top: 50%;
left: 3%;
height: 50%;
width: 100%;
transform: skew(-25deg, 0deg);
border:1px solid red;
border-top:none;
}
<div class="chevron">1</div>
<div class="chevron">2</div>
So, one div, and two pseudo-elements, properly scewed, with borders hidden, where needed.
I want to create a div with an image and text in it that looks like this.
I've managed to get something that looks like this here:
JSFiddle of pointed div
.triangle-down {
background: white;
display: inline-block;
height: 125px;
margin-left: 20px;
margin-bottom: 55px;
position: relative;
width: 200px;
cursor: pointer;
border: red solid 2px;
}
img {
margin: 10px;
}
.triangle-down:before {
border-top: 20px solid red;
border-left: 101px solid transparent;
border-right: 101px solid transparent;
content: "";
height: 0;
left: -1px;
position: absolute;
top: 127px;
width: 0;
}
.triangle-down:after {
border-top: 20px solid white;
border-left: 100px solid transparent;
border-right: 100px solid transparent;
content: "";
height: 0;
left: 0;
position: absolute;
top: 125px;
width: 0;
}
<div class="triangle-down">
<img src="http://placehold.it/180x105">
</div>
The issues I have are:
(1) The curser turns to a pointer outside the shape when it crosses the transparent borders that help create the point. I'd prefer it if the pointer appeared only when inside the visible outline of the shape.
(2) Is there a better way of doing this? I looked at trying to rotate a div to create the point as I thought this would solve the pointer issue but I can't work out how to create an isosceles triangle shape with the correct proportions this way. This would also allow me to apply a border to create the outline rather than overlay two triangles as I have in the JSFiddle. See this post for more on this - Speech bubble with arrow
Here is a version using transform: rotate
/*Down pointing*/
.triangle-down {
background: white;
display: inline-block;
height: 125px;
margin-left: 20px;
margin-bottom: 55px;
position: relative;
width: 200px;
cursor: pointer;
border: red solid 2px;
}
img {
position: relative;
margin: 10px;
z-index: 1
}
.triangle-down:before,
.triangle-down:after {
border-bottom: 2px solid red;
background: white;
content: '';
height: 50px;
left: 5px;
position: absolute;
top: 98px;
width: 54%;
transform: rotate(22deg);
z-index: 0;
}
.triangle-down:after {
left: auto;
right: 5px;
transform: rotate(-22deg);
}
<div class="triangle-down">
<img src="http://placehold.it/180x105">
</div>
This is PNG, using PS:
And for images:
See, how it is a kind of a trapezium, qith one side perpendicular, and the other titlted.
How can this layout be made in html/css, so that whatever imaage is forwarded to this div, it is always shown inside the trapezium, and it creates this fine ui.
How to create this kind of a shape in HTML/CSS?
Code after the accepted answer:
<div class="scissor"><img src="1.png" style="width:200px"></div>
and css:
.scissor{
width: 300px;
height: 150px;
background: #FF6100;
position: relative;
}
.scissor:after{
content: '';
position: absolute; top: 100%; left: 0;
width: 0;
height: 0;
border-top: 100px solid #000;
border-right: 300px solid transparent;
display: block;
}
span{
display: inline-block;
width: 80px;
height: 80px;
border: 10px solid #fff;
border-radius: 50%;
position: absolute; top: 40%; left: 50%;
z-index: 1;
transform: translateX(-50%);
}
use pseudo element - :before or :after
div{
width: 300px;
height: 300px;
background: #FF6100 url('http://www.hybworks.co.uk/wp-content/uploads/2015/05/los-angeles-auto-repair-300x300.jpg') no-repeat 0 0;
position: relative;
}
div:after{
content: '';
position: absolute; bottom: 0px; left: 0;
width: 0;
height: 0;
border-top: 150px solid transparent;
border-right: 300px solid #fff;
display: block;
}
span{
display: inline-block;
width: 120px;
height: 120px;
text-align: center;
line-height: 120px;
font-size: 60px;
font-family: 'segoe ui';
color: #fff;
border: 10px solid #fff;
border-radius: 50%;
position: absolute; top: 10%; left: 50%;
z-index: 1;
transform: translateX(-50%);
}
<div>
<span>D</span>
</div>
Example 2 - use svg
<svg width="300" height="200">
<polyline points="10, 10 300, 10 300, 100 10, 200 10, 100 10, 10" stroke-width="1" stroke="rgb(255,97,0)" fill="rgb(255,97,0)">
</svg>
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: