CSS/Web design: how to create an oblique/sided button - css

How can one create a button on a website with each side being oblique (diagonals)?
I didn't find an example to show you but this is the closest I could find in 10 minutes:
http://cfl.ca/ (see the menu with tabs: News, Video, Schedule, Standings)
However, in my case, I need that sort of design for an independant button and not for a menu tab.

Here's one (imperfect) way of doing it, though it's a little mark-up heavy:
<div class="button">
<span></span>
Some button text
<span></span>
</div>
With the CSS:
.button {
width: auto;
display: inline-block;
background-color: #f00;
height: 2em;
overflow: hidden;
}
.button span:first-child {
display: inline-block;
border-top: 1em solid #fff;
border-left: 1em solid #fff;
border-bottom: 1em solid #f00;
border-right: 1em solid #f00;
float: left;
margin-right: 1em;
}
.button span:last-child {
display: inline-block;
border-bottom: 1em solid #fff;
border-right: 1em solid #fff;
border-top: 1em solid #f00;
border-left: 1em solid #f00;
margin-left: 1em;
}
.button:hover {
background-color: #0f0;
}
.button:hover span:first-child {
border-right-color: #0f0;
border-bottom-color: #0f0;
}
.button:hover span:last-child {
border-left-color: #0f0;
border-top-color: #0f0;
}
JS Fiddle demo.
I'm not yet sure why the text-is aligned to the bottom of the .button element, but it seems to be a starting point, at least. (And any edits, or comments, left that explain/improve the answer will be welcome as soon as I get back to my desk...).
Edited to revise the demo CSS:
.button {
width: auto;
display: inline-block;
background-color: #f00;
height: 2em;
line-height: 2em; /* centering the text vertically */
}
/* other stuff */
.button span:last-child {
display: inline-block;
border-bottom: 1em solid #fff;
border-right: 1em solid #fff;
border-top: 1em solid #f00;
border-left: 1em solid #f00;
margin-left: 1em;
float: right; /* removes from the 'normal flow' */
margin-top: -2em; /* aligns vertically with the top of the parent .button div */
}
Revised JS Fiddle demo.
Edited in response to Adam's (OP's) question (in comments):
...I'm trying to understand how you did it.
The idea is based around the simple premise that the join between borders is 45°, as illustrated with the following HTML/CSS:
<span id="box"></span>
#box {
display: inline-block;
border-width: 30px;
border-style: solid;
border-top-color: red;
border-right-color: green;
border-bottom-color: yellow;
border-left-color: blue;
}
With the result:
JS Fiddle demo.
That being the case if two adjoining borders are coloured the same two right-angled triangles are created (using the same HTML as above):
#box {
display: inline-block;
border-width: 30px;
border-style: solid;
border-top-color: red;
border-right-color: red;
border-bottom-color: yellow;
border-left-color: yellow;
}
Giving:
JS Fiddle demo.
In the example above I defined the height of the containing element (.box) as 2em, and the borders of the contained span elements as 1em (making the overall height 2em, had I given the spans their own height (or width) the shape would have become more intricate:
#box {
display: inline-block;
border-width: 30px;
border-style: solid;
border-top-color: red;
border-right-color: red;
border-bottom-color: yellow;
border-left-color: yellow;
height: 30px;
}
Giving (with height):
Or, using width:
#box {
display: inline-block;
border-width: 30px;
border-style: solid;
border-top-color: red;
border-right-color: red;
border-bottom-color: yellow;
border-left-color: yellow;
width: 30px;
}
Giving:
Using both width and height allows for a partially-dissected box:
#box {
display: inline-block;
border-width: 30px;
border-style: solid;
border-top-color: red;
border-right-color: red;
border-bottom-color: yellow;
border-left-color: yellow;
width: 30px;
height: 30px;
}
Giving:
This could be useful for pseudo-3D frame effects, perhaps; particularly with :hover effects/changes.
I'm not sure if that's helped, much, but if you have any specific curiosities let me know in the comments, and I'll do my best to answer them. =)
Edited to add a pseudo-element, ::before/::after, solution.
The HTML is simplified somewhat to:
<div class="button">
Some button text
</div>
<div class="button">
Some more button text
</div>
<div class="button">
And yet more button text
</div>​
But the CSS is rather more verbose, not complex, but certainly there seems to be more of it:
.button {
width: auto;
display: inline-block;
background-color: #f00;
height: 2em;
line-height: 2em;
position: relative;
margin-left: 3em;
}
.button::before,
.button::after {
content: '';
border-color: #f00;
border-width: 1em;
border-style: solid;
position: absolute;
top: 0;
bottom: 0;
}
.button::before {
border-top-color: transparent;
border-left-color: transparent;
right: 100%;
}
.button::after {
border-right-color: transparent;
border-bottom-color: transparent;
left: 100%;
}
.button:hover {
background-color: #0f0;
}
.button:hover::before {
border-color: #0f0;
border-top-color: transparent;
border-left-color: transparent;
}
.button:hover::after {
border-color: #0f0;
border-right-color: transparent;
border-bottom-color: transparent;
}
​JS Fiddle demo.

Funnily enough thirtydot posted a link to a tutorial for this earlier today: http://www.joecritchley.com/demos/slanted-nav/
It's for a nav, but the principle should be the same.

You use oblique background images for each element, then overlap the elements to get the images to butt-up to each other visually. The only way to get around not having rectangle hit areas is to use an image map (which you probably don't want to use).

I know it's not the most "techie" answer ever but this site can generate that kind of css for you (and browser compatible if possible)

Related

Strange edges in the input fields and heights with non-integer value

I was writing some CSS for a very common user login form, except that when I logged in from another computer with the same browser (Firefox) and operating system (Ubuntu), some strange white borders emerged on the outside.
What's even stranger is that they tend to appear and disappear simply by resizing the window.
Because? how can this be prevented?
Thanks everyone for the help! :)
HTML:
<div class="npt nptFocus">
<span>Aa</span>
<input type="text" name="usr" placeholder="Nickname">
</div>
LESS:
// Palette
#main_color: blue;
#main: darken(saturate(#main_color, -97%), 25%);
#neutral: saturate(darken(#main_color, -25%), -25%);
#verde: #118769;
#rosso: #fe5f55;
#bianco: darken(saturate(#main_color, -40%), -45%);
#v_soft = 10%;
#v_medium = 25%;
#v_hard = 40%;
#neutral_dark: darken(#neutral, #v_soft);
#verde_dark: darken(#verde, #v_soft);
#rosso_dark: darken(#rosso, #v_hard);
#main_light: lighten(#main, #v_hard);
#main_dark: darken(#main, 8%);
#radius: 5px;
.npt {
display: table;
background: #bianco;
border-radius: #radius;
border: solid 1px #main_light;
width: 100%;
overflow: hidden;
input, span{
display: table-cell;
padding: 10px;
transition: 0.25s;
}
input {
border: none;
background: none;
border-radius: 0px;
color: #main;
width: 100%;
}
span {
border-right: solid 1px darken(#main_light, -15%);
color: darken(#main, -40%);
background: darken(#main_light, -25%);
padding-left: 15px;
padding-right: 15px;
width: 55px;
}
&.nptFocus {
border: solid 1px #neutral_dark;
span {
border-right: solid 1px #neutral_dark;
color: #bianco;
background: #neutral_dark;
}
}
}
SCREEN:
UPDATE 1: Added compiled CSS
.npt {
display: table;
background: #ebebfa;
border-radius: 5px;
border: solid 1px #a3a3a8;
width: 100%;
overflow: hidden;
}
.npt input,
.npt span {
display: table-cell;
padding: 10px;
transition: 0.25s;
}
.npt input {
border: none;
background: none;
border-radius: 0px;
color: #3e3e42;
width: 100%;
}
.npt span {
border-right: solid 1px #cacace;
color: #a3a3a8;
background: #e5e5e6;
padding-left: 15px;
padding-right: 15px;
width: 55px;
}
.npt.nptFocus {
border: solid 1px #6363e9;
}
.npt.nptFocus span {
border-right: solid 1px #6363e9;
color: #ebebfa;
background: #6363e9;
}
.npt.nptError {
border: solid 1px #fe5f55;
}
.npt.nptError span {
border-right: solid 1px #fe5f55;
color: #ebebfa;
background: #fe5f55;
}
.npt.nptError.nptFocus {
border: solid 1px #d38580;
}
.npt.nptError.nptFocus span {
border-right: solid 1px #d38580;
background: #d38580;
}
.npt.nptOk {
border: solid 1px #118769;
}
.npt.nptOk span {
border-right: solid 1px #118769;
color: #ebebfa;
background: #118769;
}
.npt.nptOk.nptFocus {
border: solid 1px #6cac9b;
}
.npt.nptOk.nptFocus span {
border-right: solid 1px #6cac9b;
background: #6cac9b;
}
UPDATE 2:
Following the help of #Manas Khandelwal and the tests carried out together, it seems that this is due to a browser rendering error as the logo above the form, having the width declared as a percentage, will never have a height with an integer value .
Ideas?
Really the only solution is really having to round all the heights via JavaScript?
$('.roundHeight').each(function(){
if(!$(this).is("[data-exmargin]")) $(this).attr('data-exmargin',parseFloat($(this).css('marginTop')));
var d = parseFloat($(this).attr('data-exmargin')) - ($(this).height() - Math.floor($(this).height()));
$(this).css('marginTop', d + 'px');
});
Add outline: none; to the input element;
Codepen: https://codepen.io/manaskhandelwal1/pen/WNGgQwP

CSS button - transparent arrow on both sides

I am trying to create the button below by using the pseudo-elements before and after. I do not want to manipulate the HTML DOM. I'm searching for a solution with pure CSS.
How is it possible to make the currently white border-color of these triangles transparent?
//EDIT: The marked topic does not answer my question because I need a different angle than just rotating a square. It is also not transparent. I don't want to manipulate the DOM.
//SOLVED: This is the result after using Kate Millers solution:
//EDIT2: There is another problem with the solution I use now:
Is there a way to fix the border-width of the triangles (left and right)?
Here you can see how the size changes to 14.4 and 26.4px, 26.4px:
The best solution is to reverse the triangles (so you're adding top and bottom triangles that match the button, but not on the sides). You can technically make "transparent" triangles, but you can't have that transparency apply to a different object.
One of the most important things I changed was that the background color and padding of the button has to apply to the span element (which means each button will need an interior span), not .btn.
If you replace all of your CSS about the buttons with the below, you'll have a solution that gets you at least 90% of the way there. The angle isn't perfect because it's stopping at the text. If you want to make the angle truly perfect, you'll probably need to do some absolute positioning, which would make it messy as your button sizes change.
The non-code way you can also achieve this is to create a .png or .svg with triangles that match the color of your button and insert them into the :before and :after with content: ' ';
body { margin: 20px; background:#c2c2c2; }
.btn {
display: inline-block;
text-shadow: 0 1px 0 #000;
font-weight: bold;
text-transform: uppercase;
}
.btn {
padding: 11px 40px;
color: #fff;
position: relative;
background: #a00;
}
.btn:before, .btn:after {
content: '';
border-top: 20px solid #a00;
border-bottom: 20px solid #a00;
position: absolute;
top: 0;
}
.btn:before {
border-left:20px solid transparent;
left: -20px;
}
.btn:after {
border-right:20px solid transparent;
right:-20px;
}
.btn.inset:before, .btn.inset:after {
content: '';
border-top: 20px solid transparent;
border-bottom: 20px solid transparent;
position: absolute;
top: 0;
}
.btn.inset:before {
border-right:20px solid #a00;
left: -40px;
}
.btn.inset:after {
border-left:20px solid #a00;
right:-40px;
}
<div class="btn">Text in my little banner button</div>
<div class="btn inset">Text in my little banner button</div>
I don't use, and am not really familiar with, LESS... but you can create a similar element using a span and a wrapper with pseudo elements. It does take 2 triangles for each side (hence the span).
body { margin: 20px; background: #ddd; }
.btn {
display: inline-block;
padding: 11px 40px;
color: #fff;
position: relative;
background: #a00;
text-shadow: 0 1px 0 #000;
font-weight: bold;
text-transform: uppercase;
}
.btn:after,
.btn span:after,
.btn:before,
.btn span:before {
content: "";
width: 0;
height: 0;
display: block;
position: absolute;
right: 0;
border: 10px solid transparent;
}
.btn:after {
top: 0;
border-right-color: #ddd;
border-bottom-color: #ddd;
}
.btn span:after {
bottom: 0;
border-right-color: #ddd;
border-top-color: #ddd;
}
.btn:before {
top: 0;
left:0;
border-left-color: #ddd;
border-bottom-color: #ddd;
}
.btn span:before {
bottom: 0;
left:0;
border-left-color: #ddd;
border-top-color: #ddd;
}
<div class="btn"><span>Text in my little banner button</span></div>
I realize the ends aren't really transparent, they just match the background color to appear transparent.

Make two divs appear aside each other fails even when it shouldn't

I'm trying to make two div's appear aside each other, but it just isn't working.
I'm trying to create a search bar and button that look joined together. I'm almost there, except that my button appears below, and not inline with the div.
Shouldn't this work? Where am I going wrong, and how do I get this right?
<!DOCTYPE html>
<html>
<head>
<title>Search Bar</title>
<style>
input {
border: none;
height: 18px;
outline: none;
padding: 5px;
}
button {
border: 1px solid rgba(0, 39, 59, 0.2);
margin: 0;
height: 28px;
padding: 0;
width:100px;
}
.outer {
width: 500px;
border: 1px solid #ccc;
padding: 10px;
}
.inner {
width: 395px;
border: 1px solid #ccc;
border-right:none;
}
.button {
display: inline-block;
float: right;
}
</style>
</head>
<body>
<div class="outer">
<div class="inner"><input type="text"></div>
<div class="button"><button>Search</button></div>
</div>
</body>
</html>
change css as
.inner {
-moz-border-bottom-colors: none;
-moz-border-left-colors: none;
-moz-border-right-colors: none;
-moz-border-top-colors: none;
border-color: #CCCCCC -moz-use-text-color #CCCCCC #CCCCCC;
border-image: none;
border-style: solid none solid solid;
border-width: 1px medium 1px 1px;
display: inline-block;
float: left;
width: 395px;
}
input {
border: medium none;
height: 18px;
outline: medium none;
padding: 5px;
width: 380px;
}
.button {
display: inline-block;
overflow: hidden;
}
button {
border: 1px solid rgba(0, 39, 59, 0.2);
height: 28px;
margin: 0;
padding: 0;
width: 100px;
}
Hope this will work fine for you....
add
display:inline-block;
to .inner
http://jsfiddle.net/MrdHc/
fiddle: http://jsfiddle.net/Varinder/CD3kS/
setting display:inline-block will get you there.
now there are a few interesting things with elements that are inline-block
they get default letter spacing around them which is normally 4px
they need a display:inline;zoom:1; hack to work in ie7
updated css bits:
.outer {
...
vertical-align:middle;
}
.inner {
...
display:inline-block;
*display:inline;
*zoom:1;
}
.button {
display: inline-block;
*display:inline;
*zoom:1;
/*float: right*/
margin-left:-4px;
}
.button button { height:30px; }

How to make a gradient div in the shape of a trapezoid?

I'm trying to make this image I found on Dribbble using Codepen.
I've made the bike, but I can't get the light.
I've tried several times using overflow:hidden and it isn't working.
Do you have an idea of how to do this?
What I'm trying to do is :
web here
Use triangles instead of a trapezium. You can cover the tip of said triangle with the light.
Tweak the numbers, but here's the general idea: http://jsfiddle.net/cZQmH/ http://jsfiddle.net/cZQmH/1/ (added browser compatibility)
<div class="light">
<div class="top triangle"></div>
<div class="bottom triangle"></div>
</div>
Where each "triangle" is actually just covering up the corner
.light { /* Just a big box. Where the magic happens*/
padding:50px 0px;
position: absolute;
background: -webkit-linear-gradient(left, rgba(255,255,255,1),rgba(255,255,255,1), rgba(255,255,0,0)); /* should add other compatibility things */
height: 75px;
width:200px;
}
.triangle {
width: 50px;
position: absolute;
left: 0;
}
.top { /*Covers top corner*/
top:0;
border-top: 100px solid #ff0;
border-right: 100px solid transparent;
}
.bottom { /* Covers bottom corner */
bottom:0;
border-bottom: 100px solid #ff0;
border-right: 100px solid transparent;
}
The final CSS is a bit verbose, but if you're using LESS or SASS it should come out pretty cleanly.
What it comes down to is not using the border itself, but using a gradient negative image. You could experiment with the border-image it's just as well supported as Gradients but I came up with this solution first. It does look like it's possible however
Also: could you post a link to the completed bike? I'd be curious to see how you handle all of those curves.
html
<div class="light">
<div id="trapezoid"></div>
<div id="trapezoid-two"></div>
</div>
css
.light{
background-color: yellow;
width: 400px;
height: 200px;
}
#trapezoid {
top: 50px;
left: 150px;
position: absolute;
border-top: 40px solid transparent;
border-bottom: 40px solid transparent;
height: 16px;
border-right-width: 160px;
border-right-style: dashed;
border-right-color: white;
}
#trapezoid:before {
content: '';
position: absolute;
width: 40px;
height: 10px;
-webkit-box-shadow: 3px 0 130px 80px white;
left: 160px;
border-radius: 50px;
background-color: white;
}
#trapezoid-two{
top: 60px;
left: 200px;
position: absolute;
border-top: 35px solid transparent;
border-bottom: 35px solid transparent;
height: 6px;
border-right-width: 160px;
border-right-style: solid;
border-right-color: white;
}

CSS Triangle For Testimonial Box

I have a testimonials box that I would like to add a triangle to.
.arrow {
float: left;
margin-left: 25px;
margin-top: 20px;
width: 0;
height: 0;
border-top: 20px solid #eee;
border-left: 0px solid transparent;
border-right: 25px solid transparent;
}
The problem is the triangle ends up being solid, as opposed to white with a gray border. Below is a screenshot of how the CSS currently displays. Thanks in advance for the time and help.
You can create two triangles, one that overlaps the other, to create this bordered effect. You can do this with the ::before and ::after pseudo-elements so that you don't even have any superfluous HTML.
http://jsfiddle.net/7K2c4/
.mybox {
position: relative;
border: 1px solid #ccc;
}
.mybox:before,
.mybox:after { position: absolute;
left: 20px;
bottom: -19px;
display: block;
width: 0;
height: 0;
border-width: 0 25px 20px;
border-style: solid;
border-color: transparent;
border-left-color: #fff;
content: ' ';
}
.mybox:before { left: 19px;
bottom: -21px;
border-left-color: #ccc; }
You can place another triangle over it, smaller with the same color of the box background. You don't even need to create another HTML element, just use a pseudo-element selector.

Resources