I have some buttons with text inside. What I'm trying to do is to align them to middle from vertical and horizontal.On the example I have 3 buttons (the left one is bigger in purpose)
When it a long text its placed on some rows on the middle of the button - it is not starting from the vertical middle but looks fine, but when I get short text it ("oneWord") then attached to the top side and all looks messy.
I read some exampels:
How do I vertically align something inside a span tag?
Button's text vertical align
How do I vertically align something inside a span tag?
vertical-align:middle for text in button
After all this I set my style to:
.spanContainer {
height: 70px;
}
.spanContainer span {
height: 70px;
display: table-cell;
vertical-align: middle;
white-space: normal;
}
After All the changes I'm getting those result:
On vertical side it is in middle(short and long text) - O.K, but on the horizontal for short text it start from the left side
The problem is that display: table-cell float it to left side for short text!
How can I create those buttons so even if I have one word or a long text they all will start on the middle of the button on horizontal and vertical?
Try the snippet below
CSS
.spanContainer {
height: 70px;
display: table;
width: 200px;
}
.spanContainer span {
background-color: #ff0000;
display: table-cell;
text-align: center;
vertical-align: middle;
}
Or don't use width on spanContainer, use some padding on the inner span instead
.spanContainer {
height: 70px;
display: table;
}
.spanContainer span {
background-color: #ff0000;
display: table-cell;
text-align: center;
vertical-align: middle;
padding: 0px 20px 0px 20px;
}
HTML
<span class="spanContainer">
<span>something</span>
</span>
First solution | Second solution
Related
I hava a page with two columns. I would like to textarea height mimic left column height. Left column is short when webpage loads, but when user starts expanding various properties (checkboxes + dropdownmenus) it grows based on hidden divs. But my textarea is still small in right column and making it staticly bigger does not look good.
I want it to grow per left column height. Not sure how to achieve that.
EDIT:
Once height: 100%; was added to textarea it solved the issue with columns growth.
But I ran into another two issues.
Textarea in right column overlaps that column on page load. When I try to resize, it suddenly jumps to the column properly. Weird behavior.
here is the pic - textarea overlaps column
Left column context is not aligned properly with right. How I am going to align or justify context of both columns so they end up like this:
here is the pic - final look
My CSS:
body {
height: 100%;
position: relative;
background: #000000;
color: #66adff;
font-size: 105%;
font-family: serif, Arial, Helvetica
}
.column {
border: 5px solid #333;
}
.container{
display: flex;
}
.columnleft {
width: 45%;
padding: 10px;
display: table-cell;
}
.columnright {
width: 45%;
padding: 10px;
display: table-cell;
}
textarea.out {width: 100%; height: 100%; box-sizing: border-box;}
EDIT 2:
Issue 1 - I had text inside the column which pushed area down
Issue 2 - all was fixed with proper padding
Thanks all for replies.
I think you could do this without js, but use CSS Grid instead.
Example:
.grid-container {
display: grid;
grid-template-columns: 1fr 1fr; // the width of each column
grid-template-rows: auto; // row height will auto-adjust to contents
}
<div class="grid-container">
<div class="column-left">
...some dynamic content
gets bigger and bigger and bigger and bigger and bigger
</div>
<div class="column-right">
might be empty or small or large
</div>
</div>
The grid row height will always adjust to the height of the largest content which will make both columns the same height.
Since you're using flex, the right column should be automatically adjusting to match the left column. It sounds like your issue is that the textarea is not expanding automatically to match its container (right column.)
If that's the case, try this simple fix - in your CSS, set textarea height to 100% to automatically fill its parent:
textarea {
height: 100%;
};
Here's an example answer:
Textarea to fill a parent container exactly, with padding
The reason your code wasn't working was because you didn't set the height to your textarea settting the height to 100% will always make it fit the maximum size of it's container (<div>) also i have added box-sizing: border-box; so that you can add padding to your columnright.
A better explanation about box-sizing can be found here (just won't explain here because i couldn't do better then this): https://css-tricks.com/box-sizing/
function f_anyEvent(){
var leftcolumnHeight = document.getElementById('columnleft').style.height.value;
if (document.getElementById('columnleft').style.height != document.getElementById('columnright').style.height)
document.getElementById('columnright').style.height = leftcolumnHeight.value;
}
document.getElementById('add').addEventListener('click', function() {
let columnleft = document.getElementById('columnleft');
columnleft.innerHTML += '<h1>a</h1>';
});
.row{
display: flex;
}
.column {
border: 1px solid #333;
}
.columnleft {
float: left;
width: 45%;
padding: 10px;
display: table-cell;
}
.columnright {
float: left;
width: 45%;
padding: 10px;
display: table-cell;
}
textarea {
width: 100%;
height: 100%;
box-sizing: border-box;
}
<div class="row">
<div id="columnleft" class="column columnleft">
</div>
<div id="columnright" class="column columnright">
<textarea></textarea>
</div>
</div>
<button id="add">
add
</button>
Every time you click add it will add an <h1> to your left column and your textarea will get the same height as columnleft.
Here's a basic demo of an interface similar to yours that uses display: grid on the parent container to automagically keep the two inner divs the same height. (Click on the blue details element to trigger a height change.)
It's wonderfully simple. (Thanks for inspiring me to finally learn how grid works.)
// The JavaScript isn't needed for the dynamic styling. (It just copies the text.)
const
left = document.getElementById("left"),
right = document.getElementById("right");
left.addEventListener("change", showOutput);
function showOutput(event){
right.innerHTML = this.querySelector("#reasons").value
}
div { max-width: 400px; border: 1px solid grey; }
details{ margin: 10px 5px; color: #0000DD; text-decoration: underline; }
/* This is where the magic happens */
#container { display: grid; grid-template-columns: 1fr 1fr; }
#left{ padding: 10px; }
#right { white-space: pre-wrap; }
<div id="container">
<div id="left">
<label> <input type="checkbox"/> I like pie </label>
<details>
<summary>Type your reasons here</summary> <textarea id="reasons"></textarea>
</details>
</div>
<div id="right"></div>
</div>
In short, i want a textbox bottom to top that keeps the width and height that i defined. Keeping the cursor bottom left works when adding style position:relative, which makes the div automatically grow when text is added. When using position:absolute, the cursor changes to top-left.
How to reproduce the problem:
Open the jsfiddle and write bottom right more text into the textbox until it overflows. The goal is to keep the size of the div but at the same time keep the caret bottom left
I am forced to go with a div "contenteditable=true" in order to create a nice textbox. The div is created by a server "swellrt" and i can add attributes and styles but i can not change that the text is going into this one div.
The big picture of this it is about a collaborative text editor where the server takes care about the div where all text for all users is going and taking the edits from the users from the same div, posting and getting all changes using a live webrtc channel. On client side i can only change the style and attirbutes of the div which is controlled by the server.
The caret or cursor shall basically start and (as long as not moved by the user) stay at the bottom of the document.
I was able to do this with below example, but using position:relative, the div will grow in height on overflow (when we enter a lot of text). But when changing the position to absolute, the caret will start top left again.
https://jsfiddle.net/pa0owso5/20/
<html>
<style>
.canvas {
background-color: #fff;
box-shadow: 0 4px 14px -4px #919191;
border: 1px solid #e0e0e0;
height: 200px;
width: 400px;
margin: 20px;
padding-left: 20px;
padding-top: 20px;
padding-bottom: 20px;
padding-right: 20px;
word-wrap:break-word;
vertical-align: bottom;
display: table-cell;
word-wrap:break-word;
overflow: scroll;
vertical-align: bottom;
display: table-cell;
position:relative;
}
</style>
<div contenteditable=true class="canvas">
text should start bottom left
</div>
</html>
Key css elements i use currently are:
vertical-align: bottom;
display: table-cell;
word-wrap:break-word;
position:relative;
With use of position:relative your caret is able to know where the "bottom" of your canvas is. If you use position:absolute on your canvas class, this means that you are "master of this canvas", but of course also that you have to set all values on your own. This, subsequently, means that your caret does not know automatically where bottom is.
Anyhow, you can add an additional "caret" class and give this class the information it needs to position itself.
Try following in CSS:
.canvas {
background-color: #fff;
box-shadow: 0 4px 14px -4px #919191;
border: 1px solid #e0e0e0;
height: 300px;
width: 500px;
margin: 20px;
padding-left: 20px;
padding-top: 20px;
padding-bottom: 20px;
padding-right: 20px;
word-wrap:break-word;
vertical-align: bottom;
display: table-cell;
word-wrap:break-word;
overflow: scroll;
vertical-align: bottom;
display: table-cell;
position:absolute;
}
.caret {
margin-top: 250px;
position: relative;
}
And in your HTML:
<div contenteditable=true class="canvas">
<div contenteditable=true class="caret">
testtext
</div>
</div>
Cheers!
remove display: table-cell; Then you can have overflow-y. Your div will also be of fixed height as you please. And if you want your text to start from bottom, just put a child div giving it all the attributes and transformY to -100%
If I am understanding correctly you want the caret to start at the bottom? There is an answer here: Set keyboard caret position in html textbox which may answer what you're looking for. It uses javascript to set the caret position in an element. You could determine the length of text and just set the caret to the end. Here is the code:
function setCaretPosition(elemId, caretPos) {
var elem = document.getElementById(elemId);
if(elem != null) {
if(elem.createTextRange) {
var range = elem.createTextRange();
range.move('character', caretPos);
range.select();
}
else {
if(elem.selectionStart) {
elem.focus();
elem.setSelectionRange(caretPos, caretPos);
}
else
elem.focus();
}
}
}
Title of of the album is dynamically generated from admin panel.
So the problem is when titles are not the same length.
They are used for navigating (prev and next) below actual album...
Code:
<div class="album-box">
<div class="prev-album pull-left">
Dynamically generated title
</div>
<div class="next-album pull-right">
<a href="">Dynamically generated title in
Dynamically generated title 3
Dynamically generated title rows</a>
</div>
</div>
Live:
jsfiddle
Not sure how can I position it to be in the middle vertically no matter how long the title is.
Any idea?
Thanks.
EDIT:
I would like to move elements on the left and right border.
Image:
You got plenty of good answers.
Here's one more using display:table
Non-flexbox Demo
.prev-album, .next-album {
font-size: 12pt;
padding: 20px 0;
color: red;
display: table;
}
.album-box a{
display: table-cell;
vertical-align: middle;
}
Use flex: https://jsfiddle.net/58eh0r2g/1/
Add the following code to the parent containers.
display: flex;
align-items: center;
justify-content: center;
In your case these would be .prev-album and .next-album
https://philipwalton.github.io/solved-by-flexbox/demos/vertical-centering/
This solution will lose support for some IE versions, but flex is so powerful it's worth using it.
If you are wanting to grasp a new and awesome css...thing, then I would use flexbox. Flexbox has a property called align-items that will vertically align flex items (children).
Read here: https://css-tricks.com/snippets/css/a-guide-to-flexbox/
Browser support is growing, but mobile and IE10 will need -ms- or -webkit- prefix.
Give the next-album and prev-album display: table;
Then add display: table-cell; vertical-align: middle; to the anchor tags inside of those divs.
I also updated your jsfiddle to show my answer.
https://jsfiddle.net/58eh0r2g/7/
You can set css display attribute of the album-box class to table, and child to table-cell, then you can use vertical-align: middle;
Or you could try display flex, but it's not supported by some browsers.
Here's a solution different from the ones posted so far:
jsFiddle Demo
Using a combination of transform and top/left with absolute positioning on the a tags (absolute relative to parent):
.prev-album, .next-album {
font-size: 12pt;
padding: 20px 0;
color: red;
// added this
position: relative;
}
// and these
.prev-album a, .next-album a {
padding: 10px 40px;
position: absolute;
width: 100%;
top: 50%;
left: 50%;
transform: translateX(-50%) translateY(-50%);
}
Since you want to align the text dynamically in the center of vertical axis, try using the follows:
HTML:
Content here
CSS:
#parent {display: table;}
#child {
display: table-cell;
vertical-align: middle;
}
I have modified your code s per above in this plunk : http://plnkr.co/edit/PdK9YWGUvbuGAW7S00x9?p=preview
This has been asked in various forms all over Stack Overflow but here you go, Simply add this to your CSS:
.prev-album a, .next-album a {
display: table-cell;
text-align: center;
vertical-align: middle;
}
Then change display: inline-block to display: table on both .prev-album and .next-album.
Simple update of your existing code on JSFiddle
Several improvements to your existing code on JSFiddle
You could even opt to use flex box method however older browsers will not support it, especially internet explorer. You can view the browser support for Flex Box on caniuse.com.
You could simplify your CSS by sharing properties as it will reduce code and be easier to manage:
.album-box, .prev-album, .next-album {
border-color: green;
border-style: solid;
border-width: 0;
}
.album-box {
display: block;
width: 100%;
float: left;
border-bottom-width: 2px;
}
.prev-album, .next-album {
font-size: 12pt;
height: 82px;
display: table;
padding: 10px 40px;
width: 50%;
text-align: center;
}
.prev-album {
border-right-width: 1px;
}
.next-album {
border-left-width: 1px;
}
.prev-album a, .next-album a {
display: table-cell;
vertical-align: middle;
}
I have a bunch of img elements that I want to display in a line inside a div. So I did something like this
css:
#imageContainer {
height: 90px;
padding-left: 50px;
padding-right: 50px;
text-align: justify;
text-justify: distribute-all-lines;
}
#imageContainer > img {
/*width: 150px;
height: 125px;*/
/*vertical-align: middle;*/
display: inline-block;
*display: inline;
zoom: 1;
}
#imageContainer:after {
content: '';
width: 100%;
display: inline-block;
font-size: 0;
line-height: 0;
}
html:
<div id="imageContainer">
<img class="imageOne" src="images/sample2.jpg" />
<img class="imageTwo" src="images/sample.jpg" />
</div>
This will make sure no matter how many img tag I put in the div it will be evenly distributed across the screen width. Now what I want to do is to be able to adjust vertical position of different elements. I tried to add padding in individual img tag but that will adjust the position of whole line. Is there a way to work around this?
JSFiddle: http://jsfiddle.net/g244H/
Update:
Found two solutions so far:
Don't use display inline block, use float and do something similar as Auto-growing margins when screen width get streched
But this means implementing a bunch of code to get the auto margin adjustment
With a bit of hack I have this work around, surround a div to each of img element and have display inline-block applied to div instead of img. Then in each div I can applied margin-top to adjust the height. JSFiddle link above is updated
position: relative;
top: the-amount-that-you-want-it-to-move;
Relative will make it appear to the other elements as if it's still where it was without it, but it's visible part will be moved according to top, bottom, left, and right.
For the images that you would like to raise and or lower you could do a.
margin-top:1em; margin-bottom:-1em
Add overflow:visible to the #imageContainer.
Also add position:relative; When ever positioning elements they need a position set and so does their parent.
#imageContainer {
position:relative;
height: 90px;
padding-left: 50px;
padding-right: 50px;
text-align: justify;
text-justify: distribute-all-lines;
overflow:visible
}
#imageContainer > img {
position:relative;
/*width: 150px;
height: 125px;*/
/*vertical-align: middle;*/
display: inline-block;
*display: inline;
zoom: 1;
}
The same amount you add you subtract for the opposite side.
I know how to vertically align a text center within a div when the height of text is known. Say the text's height is 20px.
Wrap the text with a span. Style div & span.
div {
position: relative;
}
span {
display: block
position: absolute;
top: 50%;
height: 20px;
margin-top: -10px;
}
Now I want to responsively align the text. What I want is the font-size of the text be in proportion to the height of the body. Say I have the following style:
body {
font-size: 100%;
}
span {
font-size: 1.5em;
}
Then I will change the font-size of body when the window size changed. In this situation, the height of the text is not determined. Then how to vertically align the text middle?
I know I can use JavaScript to dynamically change the height and margin-top of the span. But I have to do this after the window size changed. Then there is a chance that the window size changed, then the user see the the text not in the middle, then the JS code executed and the text jumped to the middle of the div. This may not be an acceptable solution.
I want to know if there is a pure CSS solution.
I guess I can use the following style to vertically align the text center.
div {
display: table-cell;
vertical-align: middle;
}
But with this solution, the margin of the div is not rendered properly. And the semantic is not right.
So is there a perfect solution?
Another purely CSS (CSS3) solution without table display properties would be to use the transform: translateY() property.
You'll need a container div and the inner span for you text:
HTML
<div id="container">
<span>Your Text</span>
</div>
CSS
#container{
position: relative;
}
#container span{
position: absolute;
top: 50%;
transform: translateY(-50%);
/* Your font-size CSS */
}
JsFiddle example:
https://jsfiddle.net/a0m4xnex/1/
You can use the same strategy for horizontal centering as well with translateX.
Helper Div can help you vertically align div
Works best for me, you can alter it accordingly
.DivParent {
height: 100px;
border: 1px solid lime;
white-space: nowrap;
}
.verticallyAlignedDiv {
display: inline-block;
vertical-align: middle;
white-space: normal;
}
.DivHelper {
display: inline-block;
vertical-align: middle;
height:100%;
}
<div class="DivParent">
<div class="verticallyAlignedDiv">
<p>Isnt it good!</p>
</div><div class="DivHelper"></div>
</div>
With flex box, you can do this: JSBIN
Essentially, here is the code (remember to add prefixes if needed):
html, body { height: 100%; margin: 0px; }
body {
display: flex;
justify-content: center; /* horizontal centering */
}
div {
align-self: center; /* vertical centering */
}
<body>
<div>Centered</div>
</body>