Slanted Edge Buttons - css

I'm trying to build buttons that look like this:
I can accomplish this using :after and CSS triangles, but I can't get that working with variable height elements. Is there any way to accomplish this and keep variable height?
Fiddle: http://jsfiddle.net/AaP47/2/

You could use a skewed div in this case. The only issue here is that as your buttons get taller, due to the skew, they will get slightly wider. This may not be an issue if you are only dealing with 1 or 2 lines. If they get very tall it may cause things to noticeably not line up exactly:
http://jsfiddle.net/AaP47/3/
.button.triangle:after {
content: "";
background-color: red;
display: block;
height: 100%;
position: absolute;
right: -30px;
top: 0;
width: 60px;
transform: skewX(-10deg);
}
This is also not completely scalable. You would need to decide on the largest height you have to support and adjust accordingly. The taller you need to support, the wider the skewed div must be.
Result (without the red): http://jsfiddle.net/AaP47/4/

Just because I had fun tinkering in a different direction and to offer an option concept even though you apparently already got an answer;
a {
padding-right: 20px;
padding-left: 20px;
text-decoration: none;
color: white;
font-weight: bold;
display: inline-block;
border-right: 30px solid transparent;
border-top: 50px solid #4c4c4c;
height: 0;
line-height: 20px;
}
a p {margin-top: -45px;}
and;
<a href="#">
<p>this is a triangle button<br/>
with multiple lines!</p>
</a>
jfiddle: http://jsfiddle.net/AaP47/6/
Cheers!

Related

How to vertically align text in a browser-independent way?

Context:
I'm trying to use CSS to display playing cards for a game I'm designing on my free time
What I'm trying to do, specifically:
Nothing revolutionary, there's a place on my cards in which I need to write some text, and I want to center the text so that it looks good
What I did:
The relevant part of the HTML is simply this:
<div class = "card_header">
<div class = "card_cost">1</div>
</div>
And the relevant CSS:
.card_header {
position: relative;
top: 110px;
box-sizing: border-box;
width: 100%;
height: 75px;
}
.card_cost {
position: absolute;
top: 50%;
right: 165px;
transform: translateY(-50%);
font-size: 60px;
font-weight: bold;
}
What's the problem:
I expected the card_cost text to be vertically centered between the top and bottom borders of the card_header, but under the browser I was using (Firefox), the text was a bit too high. I tried to fix this by using top: calc(50% + 4px);, which looks like this (a bit better):
Since it felt a bit too tweaky for my taste, I went and checked how it looked like under another browser (Safari) to see whether it looked the same, and it looks like this:
which is the opposite problem: the text is too low.
I've tried adding border: 1px dotted gray; to get a better idea of what's happening, and here's what I see (safari on the left, firefox on the right):
The text seems to be vertically centered within card_cost in Safari (which means it would probably get centered properly if I simply used top: 50%; as I originally did), but in Firefox the box seems to be bigger and text way-high within the box.
What exactly is going on here? Why is this behaving differently depending on the browser? Is there a way to make this render the same? Or, more broadly, is there any browser-independent way for me to make the text vertically centered here?
Edit:
Since someone mentioned line-height in the comments, here's what it looks like when I add line-height: 1; for card_cost (again, Safari on the left and Firefox on the right):
With this, the text doesn't seem as centered as before under Safari, and it's even more clear that the text is way-high under Firefox
I usually take approach with invincible :before on parent with 100% of height and vertical-align: middle;. That way this :before justifies other inline-block content:
// I would apply this style everywhere
.card_header,
.card_header * {
font-family: arial;
box-sizing: border-box;
}
.card_header {
position: relative;
top: 110px;
width: 100%;
height: 75px;
text-align: center;
background-color: rgba(100, 0, 0, .1);
}
.card_header:before {
content: '';
height: 100%;
display: inline-block;
vertical-align: middle;
border-left: 1px solid blue;
}
.card_cost {
display: inline-block;
font-size: 60px;
height: 60px;
font-weight: bold;
vertical-align: middle;
background-color: rgba(0, 0, 100, .1);
}
<div class="card_header">
<div class="card_cost">1</div>
</div>

Make text not wrap around icon in :before pseudoelement?

I have an icon in a :before pseudoelement, and if the textelement becomes to long and goes to the next row, I want it to not wrap around my pseudoelement but keep it's distance.
Here is a link to my example:
http://jsbin.com/yosevagaqa/1/edit?html,css,output
If you resize the window so that the text is forces into a new line, you can see the problem.
How can I avoid this?
As you can see from the other answers, there are multiple solutions!
If the size of the square in :before is always the same, one other solution would be to add
.link {margin-left:25px; text-indent:-25px;}
to the CSS. This causes the entire block to be shifted to the right, except for the first line, containing the square, which gets "outdented".
http://jsfiddle.net/MrLister/3xbfyqkh/
Or what I would prefer, with sizes in ems, so that the red square depends on the font size.
.link:before {
/* .. */
width: 1em; height: 1em;
margin-right: .5em;
}
.link {margin-left:1.5em; text-indent:-1.5em;}
Making sure, of course, that the indentation is the same as the size + the margin of the square.
http://jsfiddle.net/MrLister/3xbfyqkh/1/
Another approach, since the purpose is to make a custom "bullet", would be to treat the h5 like a list item. Then you won't need the ::before trick. You will need other tricks to make the square the right size though...
.link {
display:list-item; list-style:square;
color:red;
font-size:2em; line-height:.5em;
margin:.5em 0 .5em 1em}
.link a {
font-size:.417em; vertical-align:.3em}
http://jsfiddle.net/MrLister/3xbfyqkh/5/
You can add following CSS:
.link{
float: right;
width: calc(100% - 25px);
}
.link{
position: relative;
padding-left: 25px;
}
.link:before {
content: "";
background: red;
background-size: contain;
width: 15px;
height: 15px;
display: inline-block;
vertical-align: middle;
margin-right: 10px;
position: absolute; top: 0; left: 0;
}
<h5 class="link">A long link that might wrap and then it gets all weird and stuff</h5>

css absolute positioning over an img, that changes size

I thought I had it all working. an <img>, a div.wrapper around it (with position:relative, and an <i class="icon-edit"></i> with absolute position just beneath the right top position of the <img>. something like this:
<div class="userLogo" >
<img ng-show="user.image_url" ng-src="{{user.image_url}}" /> //data from angular, doesn't make a difference here
<div class="userEdit"><i class="icon-edit hand"></i></div>
</div>
with css (less style but you can understand):
.userLogo
{
width: 233px;
height: 233px;
img {
height:233px;
}
float: left;
//border: 1px solid #borders;
position:relative;
}
.userEdit
{
background: #bajeBack;
width: 25px;
height: 25px;
line-height: 25px;
color: #lightGreen;
position: absolute;
top: 13px;
right: 13px;
z-index: 50;
font-size: 19px;
padding: 3px 2px 2px 4px;
text-align: center;
opacity: 0.7;
.icon-edit{
}
}
and then, playing with the webapp it hit me: The image size can change! since I don't want to use a set width/height (that would distort the proportion of some images) I just set the height (to fit the design) and let the browser resize the width accordingly.
My problem; A narrow image would break the design - the edit icon would be hang in air, and not on the image at all, since it's positioned according to the userLogo.
My question: how can I do the same "absolute" positioning according to the image ? since it can't be the container. please enlight me. and don't hesitate to suggest changes to the html if needed. I'll be more the happy to learn something new!
Thanks!
If i understand you correctly, you need to constrain your image to a set space. How about using max-height and max-width.
.userLogo img {
max-height: 233px;
max-width: 233px;
}
It's pretty well supported these days: http://caniuse.com/#search=max-width

How can I get a top border tight to a font's glyphs?

I have need in a project to show rules at the baseline, x-height, and cap height of several font samples. I have baseline and x-height taken care of, but am having trouble getting a general CSS rule that will draw a border at the cap height of any font I apply the rule to. I've fiddled with the line height, but the space between a font's glyphs and the top of its layout box differs from font to font, so setting it once won't work for any font.
This Code Pen example illustrates the issue: http://codepen.io/DrSpatula/pen/BAgqG
You are now applying the line-height to the p. If you remove it there, and apply the line-height to the span.text, and set it to a value of 1.55ex, it shows properly.
So your CSS will be:
p {
font-size: 72px;
position: relative;
margin: 0;
padding: 0;
}
p span {
margin: 0;
padding: 0;
display: inline-block;
}
.sans {
font-family: sans-serif;
}
.text {
border-top: 1px solid blue;
line-height: 1.55ex;
}
.rule {
height: 1ex;
border-top: 1px dotted red;
border-bottom: 1px solid blue;
position: relative;
left: -7.25em;
width: 7.75em;
top: 1px;
}
It's very dirty, but have you tried a one pixel .gif as a repeating background then you can set it's position relative to the font?
maybe I can help.
I've made a small fiddle for you to view.
(http://jsfiddle.net/dgxJh/1/)
I fear however that with this solution you'll have to repostion the span with the pink line for every font-size and every font.
But in essence you'll position a span over your text by using following code:
span{
height: 1px;
width: 100%;
background: pink;
display: block;
position: absolute;
top: 0.6em;
}
don't forget to position your container relative

How can I make a fieldset legend-style "background line" on heading text?

I'm attempting to style heading text similar to how your default legend text appears in fieldsets; that is to say, I'd like a strikethrough-like line to come up to, but not through, the text. I can't seem to find any information on how I might accomplish this, and since on numerous other questions Google's always directed me to Stack Overflow for answers, I thought someone here may be able to give me advice.
For greater clarity. I'm attempting to get this effect on header text:
Centered Header Text
Is there any way to do this?
See: http://jsfiddle.net/thirtydot/jm4VQ/
If the text needs to wrap, this won't work. In IE7, there will be no line.
HTML:
<h2><span>Centered Header Text</span></h2>
CSS:
h2 {
text-align: center;
display: table;
width: 100%;
}
h2 > span, h2:before, h2:after {
display: table-cell;
}
h2:before, h2:after {
background: url(http://dummyimage.com/2x1/f0f/fff&text=+) repeat-x center;
width: 50%;
content: ' ';
}
h2 > span {
white-space: nowrap;
padding: 0 9px;
}
Edit:
<h2><strike> </strike>Your Text Here<strike> </strike></h2>
Here's how you can do it with a few simple tags and non-breaking spaces.
I'd use an image and call it a day, but this seemed to work for me:
CSS
fieldset {
border-right: 0px;
border-left: 0px;
border-bottom: 0px;
width: 200px;
}
legend {
margin: 0 25%;
}
HTML
<fieldset>
<legend>My Text Here</legend>
</fieldset>
That's the only way I could figure out how to do it with css. Note the width is fixed. Once again I wouldn't do this myself.
I came up with a quick, image-less solution that seems to work pretty well in IE 8+ and other browsers, whilst gracefully degrading in IE 6/7:
<h1>CSS 2.1 EXAMPLE</h1>
h1 { position: relative; text-align: center; }
h1:first-line { background-color: white; }
h1:before {
position: absolute;
z-index: -1;
content: '';
left: 0px;
right: 0px;
height: 1px;
top: 50%;
background-color: black;
}
It does come with the following limitations, though:
The text must match the overall background colour exactly, otherwise it will look weird.
If you want any kind of padding on the text, you need to use non-breaking spaces at either side of the text (see demo).
Heading text must always be on one line (works best if fixed width).
Here's a demo: http://jsfiddle.net/AndyE/3tFQJ/​
With flexbox being supported by all the latest browsers out there, and it being five years since the IE8 requirement was mentioned by the author, I wanted to have some fun building a new solution using that.
A variety of examples getting more complicated:
https://jsfiddle.net/0mL79b4h/1/
https://jsfiddle.net/0mL79b4h/2/
CSS
div {
display: flex;
align-items: center;
}
div:before,
div:after {
border: 1px solid #000000;
border-radius: 2px;
height: 2px;
display: block;
content: "";
flex: 1;
width: 100%;
}
h1 {
text-align: center;
margin: 8px;
}
HTML
<div>
<h1>Example Text</h1>
</div>
<div>
<h1>Multi-Line<br>Example Text</h1>
</div>
Pros:
Uses flexbox!
Super simple HTML.
Left and right sides can be adjusted for asymmetry.
Zero background issues, no inheriting colors, etc.
Fluid width.
Multi-Line support.
Left/Center/Right/Custom Alignment: Just adjust the flex property separately for the before and after elements, higher numbers will dedicate more space to that side. Remove one entirely to left or right align it.
Interesting effects by playing with the border style (I actually chose a round border in this example). Set height to 0px and use border-top instead for a generic line.
Cons:
Uses flexbox. Call me lazy, but I didn't build in any backward compatibility in this example so it'll look odd on a browser that supports psuedo elements but doesn't support flexbox, although last I checked that was Chrome (Firefox, etc), which are all automatically updated anyway. Might want to use some Modernizr.
Here is what I am using on a client's site: http://jsfiddle.net/TPgE4/
Pros:
No images needed - renders instantly
Uses padding to control space on both sides of text
Text can be center aligned, or left/right aligned — just add, e.g., margin-left: 8px or margin-right: 8px on h2 span style definition to make it look good
Cons:
Requires use of additional tag such as <span>...</span> inside heading tag
Text must fit on one line for good appearance
Background color on <span> element must match surrounding background color, so if you have a non-solid background image, gradient or pattern it won't match perfectly
Kind of late to the party, but this is my solution: https://jsfiddle.net/g43pt908/
Requires no images, and doesn't depend on a background color.
HTML
<div class="hr-text">
<span>Some text</span>
</div>
CSS
.hr-text {
border-top: 1px solid #999;
text-align: center;
background-color: inherit;
}
.hr-text span {
display: inline-block;
position: relative;
height: 14px;
top: -12px;
font-size: 14px;
font-style: italic;
color: #666;
background-color: inherit;
padding: 0 10px;
}
I'm not sure if this would suit your need...
h1:before, h1:after {
content: " ------------- ";
}
This doesn't feel like a very good answer, but I'm posting it anyway.
See: http://jsfiddle.net/rFmQg/
<h2><span>Centered Header Text</span></h2>
h2 {
background: url(http://dummyimage.com/2x1/f0f/fff&text=+) repeat-x center;
text-align: center
}
h2 span {
background: #fff;
padding: 0 9px
}
I don't like it because:
You have to use an image.
This. (it only works if the backgrounds match)
body { padding-top: 100px; }
div.parent {
text-align: center;
border-top: 1px solid #ccc;
}
div.parent div {
display: inline-block;
margin-top: -0.8em;
padding: 0 0.5em;
background: #fff;
}
<body>
<div class="parent">
<div>My Text Here</div>
</div>
</body>
This is a fluid-width solution that matches your design and should be ok in IE7 (though I'll admit I didn't check). There are a couple of downsides:
You lose the fieldset/legend semantics.
You can't put a transparent background on the text.
If you don't need it to be fluid-width, onteria_'s solution is probably your best bet.

Resources