Vertically align span:after relative to text - html

I made a menu with links that have "list bullets", reacting to hover, like this.
Each item is wrapped by a span, and use :after to create the bullets.
The bullets are vertically aligned to the bottom of the text, and I want them to be centered.
However, trying to center it by using vertical-align: middle; (and any other means I could manage to find) results in this this (inspecting it shows the text is properly centered on the container) and I can't seem to find any way to get it properly centered.
Here is the fiddle.

Can you try if this code does what you need:
%linkBase {
$fontSize: 40px;
line-height:40px;
font-size: $fontSize;
position:relative;
&::after {
$bulletHeight: $fontSize * 0.8;
content: '';
display: inline-block;
width: 2px;
height: 40px;
background-color: black;
top:50%;
position:absolute;
margin-top:-20px;
}
}
.link {
#extend %linkBase;
}
.linkCentered {
#extend %linkBase;
}
The idea is that you set the original link to be relative, then set the "after"element to be absolutely positioned. Then you set the "top" of that element to 50%, which pushes it half way down, then you pull it back up with a margin-top of half its height.
This is a common method of centering items.

Related

How to position a SVG element under a textbox?

I am trying to do two things:
Make a text input take all the space in a div. My current approach is left: 0; right: 0; but apparently it's not working.
Put a SVG in a relative position to the conainer div in a way that I can move it just under the text inpit (I'm working on a slider component in SVG).
You can see it in this JsFiddle
Any clues for the positioning? clear: both is of no use to send the SVG to the next line? Can I achieve a relative positioning from the container div element somehow?
UPDATE:
I've found a workaround for my positioning question (2). To use position: relative on the container div and position: absolute on both child elements (an input and a svg). See the updated JsFiddle.
Nevertheless, question (1) remains. How to make the text input fill the whole container div?
Try this to put the SVG on the next line:
.container {
width: 400px;
height: 45px;
background: gray;
}
.textfield {
clear: both;
float:left;
margin-right:100px;
}
.slider {
width: 200px;
height: 15px;
border: 1px solid #741;
}
Re part #1. Why don't you just set your input text field to be the same size as the div?
.textfield {
width: 400px;
height: 45px;
clear: both;
}
http://jsfiddle.net/M8UEv/8/
It also has the effect of moving the SVG under the text field.

Collapsing margin alignment in Firefox

TLDR: this codepen works fine in Chrome, but the alignment is off in Firefox.
I'm building a jQuery plugin which modifies a text input to give it a dropdown button on the left. In order to get the positioning right, I add a wrapper div, which is the same height as the input, so the button can be absolutely positioned on top of the input, and yet still have the same height:
#wrapper {
position: relative;
}
#overlay {
position: absolute;
top: 0;
bottom: 0;
width: 30px;
}
This works fine until the input has vertical margin: then the container grows to include the margin, and so the dropdown button grows with it. My solution to this was margin collapsing: I gave the input display:block which meant that the container ignored it's margin. All good.
input {
margin: 20px 0 40px; /* testing */
display: block;
}
But now the problem is that by default, inputs are inline elements e.g. you might want to have a submit button next to the input. So I wrapped the whole thing in a container div with display:inline-block, so another inline element like a button can happily sit next to it.
#container {
display: inline-block;
}
This works fine in Chrome, but has weird alignment issues in Firefox when there's any vertical margin on the input. Below I've added the final markup. There's also a codepen link at the top.
<div id="container">
<div id="wrapper">
<input>
<div id="overlay"></div>
</div>
</div>
<button>Submit</button>
Edit: the point is that this is a plugin and I'm trying to work with the user's existing markup and CSS e.g. they have this markup:
<input><button>Submit</button>
and their existing CSS has vertical margin on the input, and I want them to be able to just initialise my plugin on the input and it just work, without forcing them to change their markup/CSS. Now because the plugin needs to add lots of markup around the input (for the overlay and the dropdown list), I wrap it all up in a container div. This container div is the limit of our reach (and does not include the button element, or anything else they choose to put next to their inputs).
To fix this, you'll need to define a line-height in your parent div#test2. Without it, different browsers will give it different values. This will cause Firefox to cause this weird result.
Now, the line-height isn't the only problem, also the vertical-align's baseline value will generate a different result for inline elements than it is for inline-block elements that have a different height than the surrounding inline content. To fix this, change the value to top for the #container element (since that's the inline-block element).
The final result would have the following changed (only pasting the parts that changed):
#test2 {
background-color: green;
line-height:70px;
#container {
// replicate the inline nature of the input
display: inline-block;
vertical-align:top;
}
//the rest of the #test2 nested code
}
That would look like this.
Reply to comment
I've made something that does work by the requirements set. Since you said the extra code (so the divs around the input) are made by the plugin itself, I've taken the liberty of changing that a bit to make this work.
The way it can work quite easily is just not using inline-blocks at all, and sticking with the inline elements. This would change the styles to the following:
#container {
// replicate the inline nature of the input
display: inline;
}
#wrapper {
display: inline;
position: relative;
}
input {
// you'll want to make sure the typed text doesn't appear behind the overlay
padding-left:35px;
}
#overlay {
position: absolute;
top: 0px;
bottom: 0px;
left: 1px;
width: 30px;
background-color: #00C2FF;
}
Notes:
I didn't bother making the overlay cover the full height of the input, since your plugin would just make it a flag anyway. To make it cover the full height, just set negative top and bottom styles on the overlay, equal to the computed padding-top and padding-bottom (resp.) on the input. In this case, you'd have to change them to top:-5px;bottom:-5px;. (you can get the computed style via jQuery's $(input).css('padding-top'))
You could actually also remove the whole #container from it, since the only style it has now is display:inline which really doesn't add anything to the whole thing.
I've added a padding-left to your input, because otherwise you'd have to type behind the overlay, which is just silly.
Is the HTML generated by the plugin and it needs to stay exactly the same? I'm not sure I can figure out exactly why the second example is not working, but you seem to have too many div elements there. You could make since simpler:
HTML
<div id="test1">
<div id="wrapper">
<input>
<div id="overlay"></div>
<button>submit</button>
</div>
</div>
SCSS
input, button {
border: 1px solid black;
padding: 5px;
}
input {
display: inline-block;
padding-left: 35px;
}
#test1 {
background-color: yellow;
padding: 20px 0 40px 0;
#wrapper {
position: relative;
#overlay {
position: absolute;
top: 1px;
left: 1px;
width: 30px;
background-color: #00C2FF;
}
}
}
Codepen example
I've removed the margin, and instead used padding on the parent, it achieves the same thing. You'll also want some padding-left on your input field so the entered text doesn't disappear behind your overlay div.
EDIT: In case you are unable to change the markup:
SCSS:
#test2 {
background-color: green;
#container {
// replicate the inline nature of the input
display: inline-block;
padding: 20px 0 40px 0;
}
#wrapper {
// this is just here to be display:block and ignore the margin on the input
display: block;
position: relative;
}
input {
// tell parent to ignore margin
//display: block;
margin: 0;
}
#overlay {
position: absolute;
top: 1px;
bottom: 1px;
left: 1px;
width: 30px;
background-color: #00C2FF;
}
}
codepen demo
Removed the block and margin declarations from the input field, and moved the spacing to padding of the #container element.
"Disclaimer": Let me just start by saying that I did not find exactly what is causing the problems in Firefox, but I did think of an alternative way you could do it.
The way this works in both Firefox and Chrome is just to use the exact same HTML as you used for your #test1, but on top of that, also using the CSS :before pseudo-element (instead of using the #container and #wrapper). The code I used was:
#test2 {
background-color: green;
position:relative;
&:before {
content:"";
display:block;
position:absolute;
left:1px;
top:1px;
bottom:1px;
margin:20px 0 40px 0;
width:30px;
background:#00C2FF;
}
}
demo
The way this works is to simply position the :before overlay on exactly the same place as the divs previously were. As you can see, I've used most of the same styles as you did, but instead, I've put them on the :before pseudo-class.
Other answers don't know why it doesn't work on Firefox. Well, I think that Firefox has the right behavior and it's a Chrome problem.
In short, you want to align an input with a button. But the input is inside a wrapper. Then, you can use vertical-align to control the vertical aligning between the wrapper and the button, but not between the input and the button.
Here you can see an screenshot with different vertical-align:
See the code.
If you want to align the input and the button (last case in the image), you have a problem, because any of the keywords you can use with vertical-align does that. Only in case that input's top margin and bottom margin are equal, then vertical-align: middle works.
But in general, you have have another solution: vertical-align also accepts a <length> value.
And, to get a perfect alignment, you should use the formula
vertical-align: -(input bottom margin)
Or, if you want to align them even if the button has a bottom margin, then
vertical-align: -(input bottom margin) + (button button margin)
The code formula above works with inline-block <div>, but not with <buttons>.
The formula must be fixed to
vertical-align: -(input bottom margin) -(input offsetHeight)/2 + 6
In your example
(Input bottom margin) = 40px
(Input offsetHeight) = 31px
Then, you need
vertical-align: -(input bottom margin) -(input offsetHeight)/2 + 6
Demo
I could achieve it with the following.Codepen You will have to know the css applied to input and apply it to button as well
button{
position:absolute;
margin-left:5px;
}
input, button {
display: inline-block;
margin: 20px 0 40px 0;
}
please update below in your code.
input, button {
border: 1px solid #000000;
margin: 20px 0 40px;
padding: 5px;
vertical-align: top;
}
hope it will work
http://codepen.io/anon/pen/Isycu

Make text flow downwards rather than upwards?

I'm trying to make these icons with just CSS (except for the white icon). The problem I'm running into is that if my icon's name exceeds the width and starts wrapping the text starts overlapping the image (as it is shifted upwards, as seen on the second element), what I need to have the text do is shift downwards (as shown on the third element).
Here is my html:
<div class=circle><label>Manage Queries</label></div>
And here is my CSS:
.circle
{
float:left;
position:relative;
border-radius: 50%;
width: 128px;
height: 128px;
background: #C70C11 url('myimage.png') no-repeat center center;
}
.circle > label
{
font-family:arial;
position: absolute;
bottom: -20px;
text-align:center;
width:inherit;
}
I have tried vertical-align but I haven't found any success with it.
Instead of bottom:-20px, try top:100%
Here is a proof of concept: http://jsfiddle.net/eZcRk/
Just set the top property of the label to the height of the div
.circle > label
{
top: 128px;
}
DEMO
To get vertical-align to work, you need to set the parent tag to have display: table. Then you set the tag with these properties:
display: table-cell;
vertical-align: bottom;
Tried setting vertical-algin:bottom; and display:inline; for your label ?

Growing an element on the spot in CSS

I have a lot of spans that are boxes in a center tag and I want each box to grow on the spot when the user hovers over it. This doesn't work, because it shifts all the other elements along with it and doesn't look nice:
.square:hover {
background-color: yellow;
width: 50px; // originally 25px
height: 50px;// originally 25px
}
How can I get it to grow without shoving all of its neighbors aside?
I would wrap the .square in an relatively position container of the same size, then on hove make .square absolutely positioned
.squareContainer {
position:relative;
width: 25px;
height: 25px;
}
.square:hover {
position:absolute;
width: 50px;
height: 50px;
}
This way when .square is removed from the flow it doesn't affect other elements.
EDIT
Setting .square to absolute doesn't seem to work
but setting both to relative works
FIDDLE
http://jsfiddle.net/ur4aT/10/
Give .square position absolute and position it relative to it's container...
.square {
position:absolute; /* moves the element out of normal flow */
}
.square:hover {
background-color: yellow;
width: 50px; // originally 25px
height: 50px;// originally 25px
}
You may also need to alter the top and left properties in the :hover psuedo-selector since positioning is based off of the top left corner of the element:
.square { top:50px; left:50px; }
.square:hover {
/* ... definitions ... */
top:25px;
left:25px;
}
I have used the trick
set the outer divs position to inline-block to align them horizontally (not required thou')
set the width and height of outer div (required)
use % based dimensions for inner div (choose whatever you like, and it's simple to work that way).
on inner div :hover state, set it's dimensions again % based and set it's margin a/c to formula margin = (100-width)/2
Check out the demo #jsFiddle: http://jsfiddle.net/dxb28/,
best of luck :)<

Floated link within a div screws up centering of image on same line

first off I would like to say thanks to those who have helped me out before on here.
Ok the problem is this: I have several images which are placed inside a a div called "Banner"
at the top of my web site. I also have a text link to facebook which is floated to the right. They are each centered using the following css...
#banner img {border:none;
margin:0 auto;
display:block;
}
a#social_network {
float:right;
margin:10px;
padding:0px;
}
I have also floated a link to facebook to the right, which is given an id called "social_network" and is also within the banner div. The problem is that when I float this textual link right my top image is no longer centered. I thought that maybe I needed to clear the float but that did not work I was doing it wrong.
All suggestions are appreciated.
Maybe you can try this:
#banner {
position: relative:
}
#banner img {
border: none;
position: absolute;
left: 50%;
top: 50%;
margin-left: -100px; /* <--- Here's 1/2 of the width of the image */
margin-top: -50px; /* <--- Here's 1/2 of the height of the image */
}