CSS3 Menu Border - RightArrow Effect - css

I want to achieve the right arrow effect using css3, i tried a bunch of times already but no luck.
http://jsfiddle.net/ffCDw/
.menu li {
list-style-type: none;
display:inline;
}
.menu li a {
padding: 0 20px;
background: green;
color: #fff;
}

I had the same problem and the approach with the borders wasn't quite satisfying enough for me, especially if you want to use :hover...
HTML
I put a span inside the div, this is for the arrow only.
<div class="arrow">
I am the first arrow
<span></span>
<div>
CSS
span get's position:absolute;
Here the span:after is positioned and transformed (-45deg), so it points to the right.
And finally, by putting span overflow:hidden, there is only the part left visible that points to the right...
span {
content: "";
position: absolute;
top: 0;
right: -1.625em;
width: 2em;
height: 2.5em;
overflow: hidden;
z-index: 10;
}
span:after {
content: "";
position: absolute;
top: -3px;
left: -1em;
width: 2em;
height: 2.5em;
-webkit-transform: rotate(-45deg);
-moz-transform: rotate(-45deg);
-o-transform: rotate(-45deg);
-ms-transform: rotate(-45deg);
transform: rotate(-45deg);
border: 1px solid #777;
background: #60bee7;
}
I hope this is understandable. The only thing left is to style your div and span:after and if you want define the :hover states aswell on these elements.
Please note not to give the span any background-color
And here is a working example:
http://jsfiddle.net/marczking/PyKFT/

If you want to add an arrow to the right edge of these elements:
Updated fiddle
We're using CSS to add a triangle element after your anchor tag with this block:
.menu li a:after{
height:0;
width: 0;
top: 0;
left: 100%;
position:absolute;
content: ' ';
border-left: solid 5px green;
border-top: solid 9px transparent;
border-bottom: solid 9px transparent;
}
And then increasing the left margin of your li elements to account for the additional space these take up. You can play with the length of the triangle by increasing the pixel size of the border-left property, but be sure to increase the margin of the li accordingly.

Related

Stack after pseudo Element behind headline (as box-shadow alternative)

I've the following problem: I want headlines with background and a box-shadow. Now, as firefox is not rendering transform rotate like a charm, I'm looking for an alternative.
h2 {
padding: 1rem 2rem;
display: inline-block;
color: #FFF;
background-color: #006AB3;
transform: translateZ(1px) rotate(-3deg);
transform-origin: 50% 50%;
margin-bottom: rem-calc(50px);
outline: 1px solid transparent;
z-index:1;
&:after{
content: "";
width: 100%;
height: 100%;
position: absolute;
background: rgba(0,0,0,.3);
right:-10px;
bottom:-10px;
outline: 1px solid transparent;
z-index: -1;
}
}
https://jsfiddle.net/gw64ove4/
Why is the pseudo after Element not stacked behind the headline? Are there any other workarounds for anti aliasing when using box-shadow on a rotated element?
Thanks
Try adding a span in H2 tag:
<h2>
<span>TEXT</span>
</h2>
and CSS for span like this:
span {display: block; position: relative; z-index: 10;}
https://jsfiddle.net/zLna2xLa/
Also you can try using -moz- prefixes
EG::
-moz-transform: translateZ(1px) rotate(-3deg);
-moz-transform-origin: 50% 50%;

CSS: How to add slanted edge to right of div with complete browser cross-compatability?

I'm looking to achieve a slanted edge on my div. The problem I'm coming across is the simple code I found to accomplish this is not cross-browser compatible. In fact, it only shows in Chrome.
Can anyone advise on how to do the following so it works in ALL browsers:
clip-path:polygon(0 0, 70% 0, 100% 100%, 0 100%);
This effect would achieve:
Here's my entire CSS code:
.my-slanted-div {
position:absolute;
bottom:0;
left:0;
width:100px;
padding:10px 10px;
background-color:#eee;
font-size:20px;
clip-path:polygon(0 0, 70% 0, 100% 100%, 0 100%);
}
Can anyone help me out?
You can also skew pseudo-element, like this:
.my-slanted-div {
position:absolute;
bottom:40px;
left:0;
width:80px;
padding:10px 10px;
background-color:red;
font-size:20px;
}
.my-slanted-div:after {
width:50px;
background:red;
position:absolute;
height:100%;
content:' ';
right:-22px;
top:0;
transform: skew(45deg);
}
<div class="my-slanted-div">
TEXT
</div>
p.s. change angle, play with values...to get desired result...
Edit: Demo in context -> https://jsfiddle.net/Lbwj40mg/2/
This should do the trick using borders.
<div id="container">
<p id="text">Hello</p>
<div id="slanted"></div>
</div>
#container {
position: relative;
height: 200px;
width: 200px;
background:url(http://placehold.it/200x200);
}
#text {
position: absolute;
bottom: 15px;
left: 10px;
z-index: 1;
margin: 0;
}
#slanted {
position: absolute;
bottom: 0;
left: 0;
height: 0;
width: 0;
border-left: 75px solid #dedede;
border-right: 50px solid transparent;
border-bottom: 50px solid #dedede;
}
jsfiddle
I've made it work one way with :before and :after pseudos, you simply need to update the widths, heights and line-height to suit the size of tab you want; the rectangle must be the same height as the :before and :after bits for a clean look.
.box {
background: red;
width: 200px;
position: relative;
height: 100px;
line-height: 100px;
text-align: center;
margin-left: 50px;
color: white;
font-size: 21px;
font-family: arial, sans-serif;
}
.box:after {
position: absolute;
right: -50px;
content: '';
width: 0;
height: 0;
border-left: 50px solid transparent;
border-right: 50px solid transparent;
border-bottom: 100px solid red;
}
.box:before {
position: absolute;
left: -50px;
content: '';
width: 0;
height: 0;
border-left: 50px solid transparent;
border-right: 50px solid transparent;
border-bottom: 100px solid red;
}
<div class="box">
Text in the box
</div>
Here's a way with transform: rotate just to add to the list. Quite annoying as you will have to play with pixels for alignment and make some entries into #media rules for different screen sizes. But it should be fairly cross browser friendly (but maybe not opera mini)
body {
background-color: #333;
}
.container {
position: absolute; /* needs a position, relative is fine. abolsute just for this example */
top: 50%; left: 50%;
transform: translate(-50%, -50%);
width: 400px;
height: 200px;
background-color: #ccc;
overflow: hidden; /* required */
}
.salutations {
position: absolute;
bottom: 0;
left: 0;
padding: 0 10px 0 15px;
background-color: #fcfcfc;
height: 50px;
line-height: 50px; /* match height to vertically center text */
font-size: 30px;
}
.salutations::before {
content: '';
position: absolute;
top: 21px; /* play with this for alignment */
right: -36px; /* play with this for alignment */
height: 40px; width: 70px; /* may need to adjust these depending on container size */
background-color: #fcfcfc;
transform: rotate(60deg); /* to adjust angle */
z-index: -1; /* puts the pseudo element ::before below .salutations */
}
<div class="container">
<div class="salutations">Hello</div>
</div>
P.S. May have to adjust a pixel or two, my eyes suck.
Browser Compatability
transform: rotate
pseudo elements (::before)
Fiddle
https://jsfiddle.net/Hastig/wy5bjxg3/
It is most likely it is an SVG scaled to always fit its text which is simple and quick way of doing it; if you must use CSS then you could always:
Set a gradient to the div from color to transparent so that it takes up most of the div and the transition of color is abrupt and not smooth like how a normal gradient looks.
create another div and using borders create a triangle to touch the other main rectangular div such as doing:
.triangle {
width: 0;
height: 0;
border-style: solid;
border-width: 200px 200px 0 0;
border-color: #fff transparent transparent transparent;
}
Using css you can generate an element that takes the shape of a triangle.
Css tricks has a post on that.
By making the .slanted class position itself relative, we can position the generated content on the right side of the slanted div using absolute positioning.
It'll take some fiddling to get the perfect result you want, but here's an example.
.slanted{
background: #007bff;
color: #fff;
position: relative;
display:inline-block;
font-size: 20px;
height: 25px;
padding: 2px 4px;
}
.slanted::after {
content: " ";
display: block;
width: 0;
height: 0;
border-style: solid;
border-width: 29px 0 0 20px;
border-color: transparent transparent transparent #007bff;
position: absolute;
top: 0;
right: -20px;
}
<div class="slanted">Hello</div>

Semi-transparent slanted background

I want to create an html element, e.g. a div, which is styled as follows:
semi-transparent background-color
rounded borders on all edges
left side of the div draws a straight line
right side of the div draws a skewed line
I'd like to create this in CSS only and wonder if this is possible. So far I came up with two different approaches which have their own drawbacks and are not fully sufficient. You can have a look at those in this fiddle:
https://jsfiddle.net/n4tecna3/
.one-side-skew-1,
.one-side-skew-2 {
font-size: 20px;
padding: 2%;
background-color: rgba(220, 50, 255, 0.6);
position: relative;
display: block;
border-radius: 4px;
z-index: 2;
color: #ffffff;
margin-top: 30px;
}
.one-side-skew-2 {
border-top-right-radius: 0px;
}
.one-side-skew-1:after {
height: 100%;
width: 20%;
position: absolute;
top: 0;
left: 85%;
display: inline-block;
content: "";
background-color: rgba(220, 50, 255, 0.6);
-moz-transform: skewX(-10deg);
-webkit-transform: skewX(-10deg);
-ms-transform: skewX(-10deg);
-o-transform: skewX(-10deg);
transform: skewX(-10deg);
z-index: -1;
border-radius: 4px;
}
.one-side-skew-2:after {
border-top: 1em solid rgba(220, 50, 255, 0.6);
border-left: 0.25em solid rgba(220, 50, 255, 0.6);
border-right: 0.25em solid transparent;
border-bottom: 1em solid transparent;
border-top-right-radius: 4px;
left: 100%;
display: inline-block;
position: absolute;
content: "";
top: 0;
}
.container {
width: 500px;
}
<div class="container">
<div class="one-side-skew-1">
<span class="inner-text">One Side Skew With Pseudo Element Skewed</span>
</div>
<div class="one-side-skew-2">
<span class="inner-text">One Side Skew With Pseudo Element Border</span>
</div>
</div>
Approach 1 .one-side-skew-1 uses a div element with round borders and a skewed, round-bordered pseudo element to create a one-side skewed element in sum. This works great as long as the background-color is solid. For semi-transparent backgrounds you will see an ugly color overlap where the element and its pseudo-element meet.
Approach 2 .one-side-skew2 uses a div element with a pseudo behind it that consists of borders only. It's somewhat hacky but gets close to my desired result. Still, the right does not look nearly as smooth as in the first approach.
Does someone else have a good solution for this problem in CSS only? Or will I have to use a fallback solution with a semi-transparent background-image to solve this?
You can use a pseudo element for all the background and hide the overflowing parts with the overflow property on the element.
This will prevent element and pseudo element background overlapping and allow semi transparent backgrounds:
div {
position: relative;
width: 250px;
font-size: 20px;
border-radius: 4px;
overflow: hidden;
color: #fff;
padding: 1% 2%;
}
div:before {
content: '';
position: absolute;
top: 0; right: 0;
width: 100%; height: 100%;
background: rgba(220, 50, 255, 0.6);
-webkit-transform-origin:100% 0;
-ms-transform-origin:100% 0;
transform-origin: 100% 0;
-webkit-transform: skewX(-10deg);
-ms-transform: skewX(-10deg);
transform: skewX(-10deg);
border-radius: 4px 4px 6px;
z-index: -1;
}
/** FOR THE DEMO **/body {background: url('http://lorempixel.com/output/people-q-g-640-480-3.jpg');background-size: cover;}
<div>content</div>

Creating a transition on a :before or :after element

I'm using CSS3 transitions to make some fade in/out transitions on a link.
I've used the transition to make the background colour fade to nothing, but I'd like to make two "borders" fade in and also move down. The borders are not actually borders because I cannot use that to position it correctly, so I've used a psuedo element of a :before: with a 3px height to create a border effect.
My question is, is it possible to use CSS3 transitions (e.g fade in the colour or move the border down 3px)
li:hover:before{content: "";height: 3px;background-color: black;width: 100%;position: absolute;left: 0;top: -3px;}
li:hover:after{content: "";height: 3px;background-color: black;width: 100%;position: absolute;left: 0;bottom: -3px;}
http://jsfiddle.net/akxrv4zf/1/
You simply need to style the :after and :before psuedo-elements WITHOUT the :hover psuedo event.
You need styles like: li:before AND styles like: li:hover:before. Try something like below.
/* Menu link animations */
li {
transition: background-color 0.3s ease-in;
position: relative;
}
li:hover {
background-color: transparent;
}
li:before {
content: "";
height: 3px;
background-color: transparent;
width: 100%;
position: absolute;
left: 0;
top: -10px;
transition: background 0.5s, top 0.5s;
}
li:after {
content: "";
height: 3px;
background-color: transparent;
width: 100%;
position: absolute;
left: 0;
bottom: -10px;
transition: background 0.5s, bottom 0.5s;
}
li:hover:before {
content: "";
height: 3px;
background-color: black;
width: 100%;
position: absolute;
left: 0;
top: -3px;
}
li:hover:after {
content: "";
height: 3px;
background-color: black;
width: 100%;
position: absolute;
left: 0;
bottom: -3px;
}
/* General Link settings */
li {
cursor: pointer;
margin: 25px 2% 0 2%;
display: inline-block;
width: 15%;
text-align: center;
padding: 5px;
background-color: #E7DAC6;
<li>Example</li>
Yes, you can style :after and :before elements just like any other element, including transitions.
Checkout this jsFiddle.
You will have to make give content to the :after,:before elements, so you can animate from one state to another.
If they do not have content from the start they are treated as display:none and you cannot apply transitions to elements whose state starts from display:none
li:before, li:after {
content:"";
height: 3px;
background-color: transparent;
width: 100%;
position: absolute;
left: 0;
transition:all 0.3s ease-in;
}
li:before {top: 0px;}
li:after {bottom: 0px;}
li:hover:before {top: -3px;}
li:hover:after {bottom: -3px;}
li:hover:after, li:hover:before {
background-color:black;
}
Demo at http://jsfiddle.net/gaby/vmL8qt6k/1

Vertically centering content of :before/:after pseudo-elements

I'm trying to achieve something similar to this picture:
I have an image (as part of a slideshow) wrapped in a div, and with :before and :after pseudo-elements, I display two controls to move onto the next (>>) or previous (<<) images of the slideshow.
So far, I have this:
div {
position: relative;
}
div:before {
display:block;
height: 100%;
content: "stuff";
position:absolute;
top: 0; left: 0;
text-align: center;
}
I can't, however, center the content of the pseudo-elements, the text appears like this:
Is this possible to achieve? If not, what would be the most semantic workaround?
I do not want to center the element itself, only its content. I'd prefer to have the element stretched to 100% height.
Edit: http://jsfiddle.net/rdy4u/
Edit2: Also, the img is liquid/fluid, the height of the div/img are unknown, and the width is set to 800px and max-width to 80%.
Assuming your element is not an <img> (because pseudo elements are not allowed on self-closing elements), let's suppose it's a <div>, so a way could be:
div {
height: 100px ;
line-height: 100px;
}
div:before, div:after {
content: "";
...
display: inline-block;
vertical-align: middle;
height: ...;
line-height: normal;
}
If you cannot change the line-height of the div, another way is:
div {
position: relative;
}
div:before, div:after {
position: absolute;
display: block;
top: 50%;
-webkit-transform: translateY(-50%);
-moz-transform: translateY(-50%);
-ms-transform: translateY(-50%);
transform: translateY(-50%);
content: "";
width: ...
}
Otherwise, just place the indicators as a background in center position.
Using flex in the pseudo element's css it is rather easy:
.parent::after {
content: "Pseudo child text";
position: absolute;
top: 0;
right: 0;
width: 30%;
height: 100%;
border: 1px solid red;
display:flex;
flex-direction:row;
align-items: center;
justify-content: center;
}
see https://jsfiddle.net/w408o7cq/
Using flex box, you should set a fixed width and height in the parent first then
div::after {
height: 100%;
display: flex;
align-items: center;
justify-content: center;
}
I know I'm late for the party but this simple flex solution worked like a charm for me in case it helps any of you.
.main-div {
display: flex;
align-items: center;
}
.my-div-name:before, .my-div-name:after {
/* This content will be vertically centered with the attributes of the main-div */
}
You can do this without resorting to images. (Sometimes you can't, e.g. using font icons inside :before or :after).
div {
position: relative;
overflow:hidden;
}
div:before, div:after {
position: absolute;
display: block;
top: 50%;
-webkit-transform: translateY(-50%);
-moz-transform: translateY(-50%);
-ms-transform: translateY(-50%);
transform: translateY(-50%);
height:20000px;
line-height:20000px;
content: ">>";
}
Admittedly, it's a bit cheeky to use 20000px If your div will ever be larger than that, just increase the px.
In your case, you have an image inside the div, so hit that image with display:block (images don't default to display:block)
Here's the updated fiddle for your particular case. http://jsfiddle.net/rdy4u/56/
Here is a way of creating next and previous controls, using :before and :after pseudo-elements. Along with border trick to create triangles for previous/next buttons. It does not give you an area 100% of height to click, but if you make the triangle (arrows) a big enough size it should make up for that.
div {
position: relative;
width: 800px;
max-width: 80%;
border: 1px solid red;
text-align: center;
margin: 0 auto;
}
div:before, div:after {
opacity: 0.5;
display:block;
content: "";
position:absolute;
width: 0;
height: 0;
}
div:before {
top: 40%; left: 0;
border-top: 25px solid transparent;
border-right: 50px solid blue;
border-bottom: 25px solid transparent;
}
div:after {
top: 40%; right: 0;
border-top: 25px solid transparent;
border-left: 50px solid blue;
border-bottom: 25px solid transparent;
}
Here is the code working: http://jsfiddle.net/fiddleriddler/rPPMf/

Resources