In my grid, I want to do something like this:
[main row]
|[columns-10] |[columns-2][row]"above img"|
| Some text | |
| here, on |[row] image here|
| multiple | |
| lines |[row] "below img"|
| ... | |
Notice how the rows in columns-2 are evenly spaced (vertically), relative to the text in columns-10.
Zurb gets me close but the rows inside the columns-2 seem to not be aware of the height of the outer row.
Here's my (haml) code:
.row
.columns.large-10
%p #{"It does work on all browsers " * 20 }
.columns.large-2
.row.right
.columns.large-12
above img
.row.right
.columns.large-12
%img{ src: "http://www.gravatar.com/avatar/4d1795fc22c16e533fd1d11fae39fef8.png",
alt: "Baboon's logo" }
.row.right
.columns.large-12
below img
Edit: Here's the JSFiddle try to resize the window and see how the image stays in the top left corner instead of being at mid height of the large text.
You need to include jQuery library in your RoR application and change the HAML code and add a JS file with the below JS code.
HAML Code:
.row
.columns.large-10
%p #{"It does work on all browsers " * 20 }
.columns.large-2
.row.right
.columns.large-12
above img
.row.right#image-container
.columns.large-12
%img{ src: "http://www.gravatar.com/avatar/4d1795fc22c16e533fd1d11fae39fef8.png",
alt: "Baboon's logo" }
.row.right
.columns.large-12
below img
JS code with jQuery library:
var height=$('#image-container').parent().siblings().height();
var above_height=$('#image-container').siblings().height();
$('#image-container').find('img').height(height-2*above_height)
Here is the JSFiddle demo.
Related
I'm trying to create a responsive <div> with a maximally square svg image in it, and some text next to it. What I have so far is (with the help of answers to several Stackoverflow questions asked by others):
<div class = 'outer'>
<div class = 'inner'>
<svg width = '100%' height = '100%' viewBox = '-35 -35 70 70'
preserveAspectRatio = 'xMaxYMin meet' id = 'yadayadayada'
xmlns = "..." version = "1.1" xmlns:xlink = "..." xmlns:svgjs = "...">...</svg>
</div>
</div>
where the svg image is generated by SVG.js:
let image = SVG () . size ('100%', '100%')
. addTo ('.inner')
. id ('yadayadayada')
. viewBox (-35, -35, 70, 70)
. attr ({preserveAspectRatio: 'xMaxYMin meet'});
//
// SVG drawing stuff
//
With the following CSS:
div.outer::before, div.outer::after {
height: 5%;
display: block;
content: "";
margin: 0 0 0 0;
}
div.outer {
margin: 0 0 0 0;
padding-left: 5%;
padding-right: 5%;
width: 90%;
height: 90%;
}
div.inner {
width: 100%;
height: 100%;
position: relative;
}
This creates a view like this:
+------------+---------------+
| | |
| | |
| | |
| Blank | SVG |
| | |
| | |
| | |
+------------+---------------+
That is, a <div> filling the entire window, with a 5% margin on each side, and a square SVG image on its right hand side (or left hand side if I change the preserveAspectRatio to xMinYMin meet). This scales as I want when changing the size of the window. So far, so good.
But now, I want to have some text next to the image (either right or left, depending on where the image is located), with the image still fully visible, and the same size. And that's where I get stuck. It's easy to get some text there using some absolute positioning, but if I add some text inside the inner div, this has the effect of shifting down the image, so the top of the image is below the bottom of the text (even if the text is a single line, shorter than the width of the white space).
I think what is happening is that the <svg> isn't actually square, but has the same size as the inner div, making that it gets pushed out of that div if text is getting added.
Can someone suggest what to do, so I can have a maximally sized square image, with text next to it, and things still being responsive? I don't really care what happens if the window gets resized to nearly square, or to portrait mode. The intended purpose is for slides for a presentation, where I still want to have the slides look good if I switch the browser to/from full screen, remove toolbars, or connect my laptop to a beamer -- in all cases, the window will be in landscape mode, and not close to being a square.
I'm trying to create a responsive <div> with a maximally square svg
image in it, and some text next to it.
Do you want to put your text where blank is currently?
If so, it sounds like your best approach will be CSS Grid.
Start by introducing an extra <div> for the text you want to add:
<div class = "outer">
<div class = "textbox">
</div>
<div class = "inner">
[... CONTENTS OF .inner HERE...]
</div>
</div>
Then give .outer:
a display value of grid
one row
two equal columns
with the following CSS:
.outer {
display: grid;
grid-template-rows: 45vw;
grid-template-columns: 45vw 45vw;
}
This will automatically give:
.textbox a width of 45 viewport width units (ie. 45% the width of the viewport)
.inner a width of 45 viewport width units
how can i make a menu position to the top of my page while scrolling. well i can do that on my header. but not on a certain part of the page .let's say my other menu is position on a 980px height of the page . if i try to use position:fixed it will just hide the menu. even if i use z-index. here's the visual:
+________________________+
| HEADER MENU <--- Fixed menu - stays at top even when scrolling.
+¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬+
| CONTENT BEGINS |
| HERE |
| |
| OTHER MENU | <---- This must stay on the top when i hit this menu
| | and stay while scrolling
| |
| |
| |
| |
+¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬+
Here is a codepen with an example of position: sticky and a basic jquery example. Remember there are some support issues but you're mostly okay at this point. But it is something to look into if you decide to use sticky.
https://codepen.io/anon/pen/WZGxrm?editors=1111 (remove comment syntax to show one option or the other)
#otherMenu {
position: sticky;
top: 50px;
}
Adds 50 to account for the height of the header:
var menu_position = $("#otherMenu").offset().top;
$(window).on('scroll', function() {
if (($(document).scrollTop() + 50) >= menu_position){
$("#otherMenu").css({"position":"fixed", "top":"50px"});
} else { $("#otherMenu").css({"position":"static", "top":"auto"});
}
});
be sure that there's no overflow:hidden on the header container
Related Bootply: http://www.bootply.com/OdVIzrxTV5
I am creating a layout in Bootstrap where sections stack atop one another on mobile:
|---|
| A |
|---|
| B |
|---|
| C |
|---|
but split apart on desktop:
|---| |---|
| B | | A |
|---| |---|
| C |
|---|
I am using .pull-right on sections A and C to do the job, but because Bootstrap is using float, section B is automatically aligned to the top as seen above. What I really want is for section B to be vertically centered like this:
|---|
|---| | A |
| B | |---|
|---| | C |
|---|
Section B should be vertically centered with respect to A and C. I've tried applying flexbox on the row, but that disrupts the layout. I've also tried various other CSS hacks but none seemed to work correctly in a responsive manner, disrupting the layout on either mobile or desktop.
Is there any reliable, responsive solution to vertically center section B when it is of unknown height? If it helps, section B is going to be an image element.
What other CSS hacks have you tried? Just curious as I know when working the factory version of Bootstrap (no sass/less) you really do have to be picky with the CSS selectors.
That being said, perhaps a JavaScript approach might help! Here's the code, I'll walk you through some changes you could make to suit your needs.
Variable breakpoint
Change this variable to whatever pixels are set for your breakpoint. For Bootstrap the xs selector kicks in at 768 by default. You could add multiple breakpoints and use more if/else statements if you wanted to do things at other breakpoints.
First if
This will trigger when the page loads and will immediately test what the width of your screen is and change the margin if need be.
window.resize()
Anytime the window is resized a similar if statement goes off and re-calculates the margin. If you throw some text in and change the height, you'll see that it stays centred. If for some reason the browser is resized below the breakpoint, the margin is simply changed to inherit.
Some Changes
You might notice that the div is a little lower than half. This is probably just a math error on how jQuery is retrieving the height. Simply add whatever constant you want to edit it up or down.
// Where 20 is in pixels
var topMargin = (totalMargin / 2) - 20;
If you wanted to center the left div so it's always in-between sections A and C you would just have to change the topMargin calculation to use the height of the A div.
If you have any questions let me know!
$(document).ready(function() {
var breakpoint = 768;
if ($(window).width() > breakpoint) {
var totalMargin = $(window).height() - $('#vertCenter').height();
var topMargin = totalMargin / 2;
$('#vertCenter').css('margin-top', topMargin);
}
$(window).resize(function(){
if ($(window).width() > breakpoint) {
var totalMargin = $(window).height() - $('#vertCenter').height();
var topMargin = totalMargin / 2;
$('#vertCenter').css('margin-top', topMargin);
} else {
$('#vertCenter').css('margin-top', 'inherit');
}
});
});
.section-a,
.section-c {
font-size: 2em;
}
.section-b {
font-size: 4em;
}
<link rel="stylesheet" type="text/css" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css">
<div class="container">
<div class="row">
<div class="test"></div>
<div class="col-xs-12 col-sm-6 pull-right">
<div class="section-a well well-lg">A</div>
</div>
<div class="col-xs-12 col-sm-6">
<div id="vertCenter" class="section-b well well-lg">B</div>
</div>
<div class="col-xs-12 col-sm-6 pull-right">
<div class="section-c well well-lg">C</div>
</div>
</div>
</div>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js"></script>
I have a fluid layout using Twitter's bootstrap, wherein I have a row with two columns. The first column has a lot of content, which I want to fill the span normally. The second column just has a button and some text, which I want to bottom align relative to the cell in the first column.
Here's what I have:
-row-fluid-------------------------------------
+-span6----------+ +-span6----------+
| | |short content |
| content | +----------------+
| that |
| is tall |
| |
+----------------+
-----------------------------------------------
Here's what I want:
-row-fluid-------------------------------------
+-span6----------+
| |
| content |
| that |
| is tall | +-span6----------+
| | |short content |
+----------------+ +----------------+
-----------------------------------------------
I've seen solutions that make the first span an absolute height, and position the second span relative to it, but a solution where I didn't have to specify the absolute height of my divs would be preferred. I'm also open to a complete rethink of how to achieve the same effect. I'm not married to this use of the scaffolding, it just seemed to make the most sense to me.
This layout as a fiddle:
http://jsfiddle.net/ryansturmer/A7buv/3/
This is an updated solution for Bootstrap 3 (should work for older versions though) that uses CSS/LESS only:
http://jsfiddle.net/silb3r/0srp42pb/11/
You set the font-size to 0 on the row (otherwise you'll end up with a pesky space between columns), then remove the column floats, set display to inline-block, re-set their font-size, and then vertical-align can be set to anything you need.
No jQuery required.
Please note: for Bootstrap 4+ users, please consider Christophe's solution (Bootstrap 4 introduced flexbox, which provides for a more elegant CSS-only solution). The following will work for earlier versions of Bootstrap...
See http://jsfiddle.net/jhfrench/bAHfj/ for a working solution.
//for each element that is classed as 'pull-down', set its margin-top to the difference between its own height and the height of its parent
$('.pull-down').each(function() {
var $this = $(this);
$this.css('margin-top', $this.parent().height() - $this.height())
});
On the plus side:
in the spirit of Bootstrap's existing helper classes, I named the class pull-down.
only the element that is getting "pulled down" needs to be classed, so...
...it's reusable for different element types (div, span, section, p, etc)
it's fairly-well supported (all the major browsers support margin-top)
Now the bad news:
it requires jQuery
it's not, as-written, responsive (sorry)
You can use flex:
#media (min-width: 768px) {
.row-fluid {
display: flex;
align-items: flex-end;
}
}
You need to add some style for span6, smthg like that:
.row-fluid .span6 {
display: table-cell;
vertical-align: bottom;
float: none;
}
and this is your fiddle: http://jsfiddle.net/sgB3T/
Here's also an angularjs directive to implement this functionality
pullDown: function() {
return {
restrict: 'A',
link: function ($scope, iElement, iAttrs) {
var $parent = iElement.parent();
var $parentHeight = $parent.height();
var height = iElement.height();
iElement.css('margin-top', $parentHeight - height);
}
};
}
Just set the parent to display:flex; and the child to margin-top:auto. This will place the child content at the bottom of the parent element, assuming the parent element has a height greater than the child element.
There is no need to try and calculate a value for margin-top when you have a height on your parent element or another element greater than your child element of interest within your parent element.
This is based on cfx's solution, but rather than setting the font size to zero in the parent container to remove the inter-column spaces added because of the display: inline-block and having to reset them, I simply added
.row.row-align-bottom > div {
float: none;
display: inline-block;
vertical-align: bottom;
margin-right: -0.25em;
}
to the column divs to compensate.
Based on the other answers here is an even more responsive version. I made changes from Ivan's version to support viewports <768px wide and to better support slow window resizes.
!function ($) { //ensure $ always references jQuery
$(function () { //when dom has finished loading
//make top text appear aligned to bottom: http://stackoverflow.com/questions/13841387/how-do-i-bottom-align-grid-elements-in-bootstrap-fluid-layout
function fixHeader() {
//for each element that is classed as 'pull-down'
//reset margin-top for all pull down items
$('.pull-down').each(function () {
$(this).css('margin-top', 0);
});
//set its margin-top to the difference between its own height and the height of its parent
$('.pull-down').each(function () {
if ($(window).innerWidth() >= 768) {
$(this).css('margin-top', $(this).parent().height() - $(this).height());
}
});
}
$(window).resize(function () {
fixHeader();
});
fixHeader();
});
}(window.jQuery);
Well, I didn't like any of those answers, my solution of the same problem was to add this:<div> </div>. So in your scheme it would look like this (more or less), no style changes were necessary in my case:
-row-fluid-------------------------------------
+-span6----------+ +----span6----------+
| | | +---div---+ |
| content | | | & nbsp; | |
| that | | +---------+ |
| is tall | | +-----div--------+|
| | | |short content ||
| | | +----------------+|
+----------------+ +-------------------+
-----------------------------------------------
.align-bottom {
position: absolute;
bottom: 10px;
right: 10px;
}
Let's say I have a static webpage and the whole page is wrapped, let's say inside a width of 700px, now if the content of the page is too long then (obviously) a scrollbar appears. BUT the appearance of the scrollbar moves everything to the left of like a few pixels (the ones needed to fit the scrollbar on the right side of the page). What I'd like to do is to remove this "moving" effect, so that if a scrollbar is needed this doesn't affect the content of the page in any way.
I don't know if I made myself clear.
let's say that this is a webpage:
| .........contentcontent ........ |
| .........contentcontent ........ |
| .........contentcontent ........ |
| .........contentcontent ........ |
| .........contentcontent ........ |
| .........contentcontent ........ |
| .........contentcontent ........ |
and this is how it looks with the scrollbar:
| .....contentcontent .......... | |
| .....contentcontent .......... | |
| .....contentcontent .......... | |
| .....contentcontent .......... | |
|......contentcontent .......... | |
| .....contentcontent .......... | |
| .....contentcontent .......... | |
but I'd like to have something like this:
| .........contentcontent ...... | |
| .........contentcontent ...... | |
| .........contentcontent ...... | |
| .........contentcontent ...... | |
| .........contentcontent ...... | |
| .........contentcontent ...... | |
| .........contentcontent ...... | |
dots represent whitespace, content represent the webpage content and the column on the right represents the scrollbar.
You can set overflow-y: scroll as rule for your body. This will always display a vertical scrollbar which is disabled unless the content is long enough to be scrolled. This way the content won't shift to the left when its long enough that you can actually scroll and no scripting is needed to make this work.
if you are not need scrollbar at all, you can use this:
body {
overflow-y: hidden;
}
UPD. so if you need scrollbar to scroll content, but want to hide it, you can use the following method (demo on dabblet.com):
css:
body {
overflow: hidden;
}
#fake_body {
position: absolute;
left: 0;
top: 0;
right: -32px;
bottom: 0;
overflow-y: scroll;
}
html:
<div id="fake_body">
<ul>
<li>content content content #01</li>
<li>content content content #02</li>
<li>content content content #03</li>
…
<li>content content content #55</li>
</ul>
</div>
The following is not supported well across browsers, as per
MDN docs, however I think you may find it interesting.
overflow-y: overlay;
In browsers that support the property, such as Google Chrome, this will put the scrollbar on top of your content instead of shifting your content over when a scrollbar is needed. You could then add a sufficient amount of padding so that your content is never covered up by it.
It seems this property is not popular, and even browsers that support it now are planning to drop support for it. I don't understand why, because it certainly has its uses.
I had the same problem and only solution using JS/jQuery was enough good for me.
I used link to Detect if a page has a vertical scrollbar? provided before and those links: http://davidwalsh.name/detect-scrollbar-width, http://api.jquery.com/css/#css2, Center a position:fixed element for generating the following code.
css:
body {
position: absolute;
left: 50%;
margin-left: -400px;
width: 800px;
height: 100%;
}
.scrollbar-measure {
width: 100px;
height: 100px;
overflow: scroll;
position: absolute;
top: -9999px;
}
JS:
$(document).ready(function() {
// Check if body height is higher than window height :)
if ($(document).height() > $(window).height()) {
// Create the measurement node
var scrollDiv = document.createElement("div");
scrollDiv.className = "scrollbar-measure";
document.body.appendChild(scrollDiv);
// Get the scroll bar width
var scrollbarWidth = scrollDiv.offsetWidth - scrollDiv.clientWidth;
// Delete the DIV
document.body.removeChild(scrollDiv);
// Change margin-left parameter for #container for preventing shift caused by scroll bar
var current_margin_left_px = $("#container").offset().left;
var current_margin_left = parseInt(current_margin_left_px, 10);
var changed_margin_left = current_margin_left + scrollbarWidth/2 + "px";
$("#container").css("margin-left", changed_margin_left);
}
});
In case of flexible body width some more code has to be added.
you can check if the screen has a scroll bar. if true than you could margin the content to the right maybe this link will help you : Detect if a page has a vertical scrollbar?
overflow-x: hidden;
in the body CSS code, HELPED AlOT! Damn, took me 45mins to surf around for a simplistic answer.
what went wrong? ...I had an with a hover=show image thing going on. I resized all the images correctly; when I refreshed the page, the scrollbar had way to much play room!.....So i put an overflow-x into each and every div tag, (each div tag assigned to individual list item), and nothing happened!
solution: The code was correct, but the placement needed to be in the body tag itself. not the individual div tags. Damn.....thankz