Im looking for a way to recreate this button with CSS only.
I know about the triangle technique and I also know how to add a border to it, but unfortunately I don't know any way to recreate this button (without adding additional wrappers or using images).
The buttons I need this style on are <input["submit"]> and ordinary <a>'s.
With one element, you could do it using gradients and skewed pseudo-elements for a link:
demo
(you could actually do it using just gradients, but then a hover action won't be triggered on hover on the arrow shape itself, but on hover on the rectangular element containing it)
HTML:
<a class='boo' href='#'>click me</a>
Relevant CSS:
.boo {
display: inline-block;
position: relative;
padding: .5em 2em;
background:
linear-gradient(60deg, dodgerblue 50%, transparent 50%) 100% 0,
linear-gradient(-60deg, transparent 50%, dodgerblue 50%) 100% 100%,
linear-gradient(-90deg, transparent 1em, dodgerblue 1em);
background-repeat: no-repeat;
background-size: 1em 50%, 1em 50%, 100% 100%;
}
.boo:before, .boo:after {
position: absolute;
right: -.2em;
width: .5em; height: 50%;
background: dodgerblue;
content: '';
}
.boo:before {
top: 0;
transform: skewX(30deg);
}
.boo:after {
bottom: 0;
transform: skewX(-30deg);
}
EDIT:
If your background is a solid color, not an image or a gradient, you could do it in a much simpler way, without using gradients (which means that this second method also has the advantage of working in IE9).
demo #2
.boo {
display: inline-block;
position: relative;
padding: .5em 2em;
background: lightblue;
}
.boo:before, .boo:after {
position: absolute;
right: -.3em;
width: .5em; height: 50%;
box-shadow: -.2em 0 0 white;
background: inherit;
content: '';
}
.boo:before {
top: 0;
transform: skewX(30deg);
}
.boo:after {
bottom: 0;
transform: skewX(-30deg);
}
You should use a background image. Create a transparent png containing the arrow.
You would need two elements, the outer would contain the background image, the inner would contain the text, and a background color which is the same as the one on the arrow. Alternatively, you could use a second background image instead of a background color, for example if your button is not just a flat color.
The trick is to align the box containing the text with the background image.
If your arrow is 20px tall, your inner box could be e.g. 16px plus 2px padding on each side (search for box model if you would like to understand this better).
The outer element can have a right-margin set to the approximate width of the arrow image.
I hope this makes sense. The general technique is called sliding doors. I suggest reading the entire article if you have the time.
Related
I am styling a text element and I want to make a fancy corner. I have come up with this code as a solution.
.top-corner {
background:
linear-gradient(to left, black 6px, transparent 6px) 100% 0,
linear-gradient(to bottom, black 6px, transparent 6px) 100% 0;
background-repeat: no-repeat;
background-size: 40px 40px;
width: fit-content;
padding-right: 20px;
}
It looks good an I have no initial problem with it.
https://fwb.crazychickentech.com/test/
The problem occurs when I start changing the font size. What I really want to do is something like this.
background-size: "this in px" = that -> 50%; - So basically, I want the first value (top) to be what every the second value (right) is but in pixels (not a percentage because then it would be 50% of the width.
I have been reading as much as I can but I'm just not getting anywhere (or understanding it).
I did look at some jQuery, but if I am totally honest, that's not my strong point.
I was also thinking of making a second div or something beside it, but at this point I'm worried I may be making things more complex than they need to be and I'm not thinking clearly.
Any suggestions or thoughts would be greatly appreciated!
Thanks all,
Happy Coding!
Pseudo element can do this:
h1 {
position: relative;
padding: 0 10px;
display: table;
margin: auto;
}
h1::before,
h1::after {
content: "";
position: absolute;
top: 0;
right: 0;
height: 50%;
width: 5px;
background: red;
}
h1::after {
transform-origin: top left;
transform: translate(100%) rotate(90deg);
}
<h1>A title here</h1>
<h1 style="font-size:50px">A title here</h1>
<h1 style="font-size:100px">A title here</h1>
I'm coding a short css button with a small image using base:64. I'd like to invert the base:64 image without inverting the linear-gradient background color. I could be less lazy and just create an invert of the base:64 image, but I feel I can just do this quicker in CSS however I can't figure out where to place the filter:invert(1) in my css shorthand. Thoughts?
Button looks like this, I just want the icon to be inverted from black to white using filter:invert(1)
https://gyazo.com/13913ed0d5713b5c62892d5f90be7518
:host {
background:url('
data:image/svg+xml;utf8;base64,PD94bWwgdmVyc2lvbj0iMS4wIj8+CjxzdmcgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiBoZWlnaHQ9IjQ4IiB2aWV3Qm94PSIwIDAgNDggNDgiIHdpZHRoPSI0OCI+PHBhdGggZD0iTTI0IDEydjZsOC04LTgtOHY2Yy04Ljg0IDAtMTYgNy4xNi0xNiAxNiAwIDMuMTQuOTIgNi4wNSAyLjQ4IDguNTJsMi45Mi0yLjkyYy0uODktMS42Ny0xLjQtMy41Ny0xLjQtNS42IDAtNi42MyA1LjM3LTEyIDEyLTEyem0xMy41MiAzLjQ4bC0yLjkyIDIuOTJjLjg5IDEuNjcgMS40IDMuNTcgMS40IDUuNiAwIDYuNjMtNS4zNyAxMi0xMiAxMnYtNmwtOCA4IDggOHYtNmM4Ljg0IDAgMTYtNy4xNiAxNi0xNiAwLTMuMTQtLjkyLTYuMDUtMi40OC04LjUyeiIvPjxwYXRoIGQ9Ik0wIDBoNDh2NDhoLTQ4eiIgZmlsbD0ibm9uZSIvPgoJCgkKCTxtZXRhZGF0YT4KCQk8cmRmOlJERiB4bWxuczpyZGY9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkvMDIvMjItcmRmLXN5bnRheC1ucyMiIHhtbG5zOnJkZnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvMDEvcmRmLXNjaGVtYSMiIHhtbG5zOmRjPSJodHRwOi8vcHVybC5vcmcvZGMvZWxlbWVudHMvMS4xLyI+CgkJCTxyZGY6RGVzY3JpcHRpb24gYWJvdXQ9Imh0dHBzOi8vaWNvbnNjb3V0LmNvbS9sZWdhbCNsaWNlbnNlcyIgZGM6dGl0bGU9IlVwZGF0ZSwgQXV0b3JlbmV3LCBSZWZyZXNoLCBSZWxvYWQiIGRjOmRlc2NyaXB0aW9uPSJVcGRhdGUsIEF1dG9yZW5ldywgUmVmcmVzaCwgUmVsb2FkIiBkYzpwdWJsaXNoZXI9Ikljb25zY291dCIgZGM6ZGF0ZT0iMjAxNi0xMi0xNCIgZGM6Zm9ybWF0PSJpbWFnZS9zdmcreG1sIiBkYzpsYW5ndWFnZT0iZW4iPgoJCQkJPGRjOmNyZWF0b3I+CgkJCQkJPHJkZjpCYWc+CgkJCQkJCTxyZGY6bGk+R29vZ2xlIEluYy48L3JkZjpsaT4KCQkJCQk8L3JkZjpCYWc+CgkJCQk8L2RjOmNyZWF0b3I+CgkJCTwvcmRmOkRlc2NyaXB0aW9uPgoJCTwvcmRmOlJERj4KICAgIDwvbWV0YWRhdGE+PC9zdmc+Cg==
') no-repeat center 15% / 35%, linear-gradient(rgb(32,56,71), rgb(13,135,199)) top left / cover no-repeat;
background-color: rgb(13,135,199); /* Incase Gradient Fails */
border-radius:10px;
}
Filters apply to the whole element and all its ancestors.
You can not target a single part of this element, nor can you target only one background-image.
One solution would be to place the background-image to be filtered on a pseudo-element:
.host {
background: linear-gradient(rgb(32, 56, 71), rgb(13, 135, 199)) top left / cover no-repeat;
background-color: rgb(13, 135, 199);
/* Incase Gradient Fails */
border-radius: 10px;
width: 50vw;
height: 50vw;
position: relative;
}
.host::before {
filter: invert(1);
content: "";
width: 100%;
height: 100%;
left: 0;
right: 0;
position: absolute;
background: url('data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIj8+CjxzdmcgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiBoZWlnaHQ9IjQ4IiB2aWV3Qm94PSIwIDAgNDggNDgiIHdpZHRoPSI0OCI+PHBhdGggZD0iTTI0IDEydjZsOC04LTgtOHY2Yy04Ljg0IDAtMTYgNy4xNi0xNiAxNiAwIDMuMTQuOTIgNi4wNSAyLjQ4IDguNTJsMi45Mi0yLjkyYy0uODktMS42Ny0xLjQtMy41Ny0xLjQtNS42IDAtNi42MyA1LjM3LTEyIDEyLTEyem0xMy41MiAzLjQ4bC0yLjkyIDIuOTJjLjg5IDEuNjcgMS40IDMuNTcgMS40IDUuNiAwIDYuNjMtNS4zNyAxMi0xMiAxMnYtNmwtOCA4IDggOHYtNmM4Ljg0IDAgMTYtNy4xNiAxNi0xNiAwLTMuMTQtLjkyLTYuMDUtMi40OC04LjUyeiIvPjxwYXRoIGQ9Ik0wIDBoNDh2NDhoLTQ4eiIgZmlsbD0ibm9uZSIvPgoJCgkKCTxtZXRhZGF0YT4KCQk8cmRmOlJERiB4bWxuczpyZGY9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkvMDIvMjItcmRmLXN5bnRheC1ucyMiIHhtbG5zOnJkZnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvMDEvcmRmLXNjaGVtYSMiIHhtbG5zOmRjPSJodHRwOi8vcHVybC5vcmcvZGMvZWxlbWVudHMvMS4xLyI+CgkJCTxyZGY6RGVzY3JpcHRpb24gYWJvdXQ9Imh0dHBzOi8vaWNvbnNjb3V0LmNvbS9sZWdhbCNsaWNlbnNlcyIgZGM6dGl0bGU9IlVwZGF0ZSwgQXV0b3JlbmV3LCBSZWZyZXNoLCBSZWxvYWQiIGRjOmRlc2NyaXB0aW9uPSJVcGRhdGUsIEF1dG9yZW5ldywgUmVmcmVzaCwgUmVsb2FkIiBkYzpwdWJsaXNoZXI9Ikljb25zY291dCIgZGM6ZGF0ZT0iMjAxNi0xMi0xNCIgZGM6Zm9ybWF0PSJpbWFnZS9zdmcreG1sIiBkYzpsYW5ndWFnZT0iZW4iPgoJCQkJPGRjOmNyZWF0b3I+CgkJCQkJPHJkZjpCYWc+CgkJCQkJCTxyZGY6bGk+R29vZ2xlIEluYy48L3JkZjpsaT4KCQkJCQk8L3JkZjpCYWc+CgkJCQk8L2RjOmNyZWF0b3I+CgkJCTwvcmRmOkRlc2NyaXB0aW9uPgoJCTwvcmRmOlJERj4KICAgIDwvbWV0YWRhdGE+PC9zdmc+Cg==') no-repeat center 15% / 35%
}
.host:hover::before {
filter: none;
}
<div class="host"></div>
I am making a One-Page webstie to practise Flexbox etc.
To do that, Im using PSD file and I have some troubles.
I wanna make rectangle with an oblique upper side with opacity on my background, i read about svg and should I do it with that like on this picture:
(brown thing with opacity throughout the website view)
I have again similar problem. I have a pic:
And it should looks like:
Tips will be great
You could do this with a CSS gradient.
Here I have a <div> with two backgrounds:
the image
a CSS linear gradient on top of it.
The sharp edge of the gradient works because there are two gradient steps that coincide. Meaning the gradient colour jumps straight from transparent to 50% blue.
I've used blue so that it shows up well in this example. In your case, just switch it to brown.
div {
width: 1240px;
height: 648px;
background: linear-gradient(175deg, rgba(0,0,200,0) 0%, rgba(0,0,200,0) 70%, rgba(0,0,200,0.5) 70%, rgba(0,0,200,0.5) 100%),
url(https://i.stack.imgur.com/Rq6eR.jpg);
}
<div></div>
Another approach without gradient.
Create a wrapper
It can be the div with background image. Important thing is you need to overflow: hidden and position: relative.
Create a rectangle and rotate it
You can create a :before pseudo element like this:
.wrapper {
position: relative;
width: 100%;
height: 200px;
background: red;
overflow: hidden;
}
.wrapper:before {
content: '';
position: absolute;
display: block;
background: blue;
opacity: .5;
bottom: -100px;
left: -100px;
right: -100px;
height: 150px;
transform: rotate(-5deg);
}
<div class="wrapper"></div>
If I want to have a blue bar in the background at the top of my webpage (so the body element's background), but I want it to be 100px in height and span the entire horizontal background... is there any way to do this without making a background image that is 100px with the color I want (and maybe 1px in width) and making it repeat-x?
Basically, rather than doing:
background: url("images/pagestripe.png") repeat-x;
I want to do this:
background: #FFCCFF 100px top left repeat-x;
Which would give me a 100px background of the color #FFCCFF that starts in the top left of the page and repeats horizontally.
Similarly, if I wanted it to repeat-y, it would make the 100px the width instead of the height.
The positioning markers can represent offsets...
Is this possible? Is there actual CSS code for what I am looking for? Perhaps I'm not far off...
You can do it using linear gradients:
body {
background-image: -moz-linear-gradient(top, blue 100px, transparent 0);
background-image: -o-linear-gradient(top, blue 100px, transparent 0);
background-image: -webkit-linear-gradient(top, blue 100px, transparent 0);
background-image: linear-gradient(top, blue 100px, transparent 0);
}
Edit: This is CSS3 only. For CSS2 you may try
body:before {
content: ' ';
display: block;
top: 0;
position: absolute;
height: 100px;
width: 100%;
background: blue;
}
You could make the bar a separate div and set a negative margin on it. Something like this:
<div id="bluebar"></div>
Content goes here...
And then in CSS:
div#bluebar {
background: #fcf; /* that's actually pink, but whatever... */
height: 100px;
margin-bottom: -100px;
}
I'd give a jsFiddle link, but they're apparently down for maintenance right now, so here's a simple static HTML demo instead.
Yes it can be done.
You can create a single full width element with the height and background color you desire.
Use CSS to position the element.
div#bluebar {
background: #acf;
display: block;
height:100px;
width:100%;
position: absolute;
top: 0px; /* however far from the top you would like it*/
left: 0px;
z-index: 10; /* or some other number that will place it below the appropriate elements */
}
Just be sure that the parent of #blubar does not have position:relative; set or it will position relative to the parent not the document.
Im able to give the start position of an background image. But if i give positions for solid fill background its not working.
Here is the js fiddle for that.
http://jsfiddle.net/yPVJE/
So can we set the start position and the size of an solid fill backgrounds?
Thanks!
I would take a similar approach to StuR, but using background position instead of gradient points. You can then set your background position as you would usually.
div {
background:linear-gradient(left, #000, #000) no-repeat 50px 50px;
}
This is one way to offset a solid background color, using a linear gradient with a transparent colour for the first x number of pixels:
.offset {
background-image: linear-gradient(left, transparent 300px,rgba(39,39,39,.5) 300px, rgba(39,39,39,.5) 100%);
width: 100%;
height: 500px;
}
Here's a demo on JSFiddle.
You can not offset a background color. Only background images have a position.
If you can make a ::before pseudo element with bg color, height and width and just offset it from its parent, you'll have complete control of its appearance. Much easier than putting a border in the pseudo element:
/* adding a ::before element with bg and border radius to create a
cropped circle to overlay parent bg image's blue right end */
.myElement::before {
background-color: #fff;
content: "";
margin: 0 auto;
position: absolute;
top: 43px;
right: 0;
width: 300px;
height: 201px;
z-index: -1;
border-top-right-radius: 8px;
border-bottom-right-radius: 8px;
}
Yes, with linear-gradient it works:
div { background-image: linear-gradient(transparent 10px, grey 10px); }
Watch out for improper alignment when linear-gradient points are used.
Here's a better approach:
background: linear-gradient(#6699cc, #6699cc);
background-size: auto 4em;
background-repeat: no-repeat;
It uses linear-gradient just to generate solid color, which is then resized to reflect the covered area size.
Also background-position could be used as needed, for example:
background: linear-gradient(#6699cc, #6699cc);
background-size: calc(100% - 30px) auto;
background-repeat: no-repeat;
background-position: right;
In the last example, the background color would 'start' 30px from the left of the div.
Further reading:
https://developer.mozilla.org/en-US/docs/Web/CSS/gradient/linear-gradient
https://developer.mozilla.org/en-US/docs/Web/CSS/background-size
https://developer.mozilla.org/en-US/docs/Web/CSS/calc
https://developer.mozilla.org/en-US/docs/Web/CSS/background-repeat
https://developer.mozilla.org/en-US/docs/Web/CSS/background-position
You can use background-size instead of background-position to restrict the colored area:
// randomly set background size every 1 second
var elm = document.querySelector('div');
window.setInterval(()=> {
var randomValue = Math.random()*100;
elm.style.backgroundSize = randomValue + '%';
}, 1000)
div {
height: 100px;
border: 1px solid black;
transition: .4s ease-out;
background: linear-gradient(to right, black, black) no-repeat;
background-size: 0; /* <--- starting from 0% */
}
<div></div>
Another way to accomplish this would be to add a pseudo-element to the div element like so:
div {
::before {
border-top: 10px solid #0066a4;
content:"";
margin: 0 auto; /* this centers the line to the full width specified */
position: absolute; /* positioning must be absolute here, and relative positioning must be applied to the parent */
top: 12px; left: 0; right: 0; bottom: 0;
z-index: -1;
}
}
See this CodePen by Eric Rasch for a working example: https://codepen.io/ericrasch/pen/Irlpm
You can achieve this by having the parent element and child element position: relative;. Next, you can just go in and set offsets. There are a few other ways to achieve this but this is one of the many takes.
SCSS:
HTML:
EXAMPLE:
Note this might have side effects for buttons and links. Test it for your use case. Good luck!
Happy Coding