Responsive image and text - html

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

Related

Getting size of previously rendered image for image overlay

i am looking for a way to get the size of a rendered image within a webpage, which size is defined as a percentage value.
I need this because of a relative positioning of 2 images which should be invariant go the size of the browser window, as well as the zooming of the site.
I did some research and this one here describes my problem pretty well:
Button width as a percentage of parent
Quote:
"To set a percentage height, its parent element must have an explicit height."
Here are the relevant parts of my project:
<div style="display: block; width:90%; height:100%; background-color:rgba(128,128,0,0.5)">
<button style=#myStyle #onclick="#(e => doFunction(5))"> </button>
with myStyle:
myStyle = "top: -30%; left: 0%; width: 15%; height: 15%; overflow: hidden; background-color: rgba(201, 76, 76, 0.3); position: relative;"
So, i got the button within a structure, and the size of the structure is again given as a percentage with respect to its superordinate structure. (but this topmost structure then has absolute values).
Is there a way to calculating and getting the absolute values (width/height) of the first structure "while rendering"?
I hope i could explain my problem sufficiently understandable, i'm happy about any answers regarding this problem, even if the answer is "it does not work like that". Thanks!
I would do it like this:
Give your image an ID:
<div id="some-id" style="display: block; width:90%; height:100%; background-color:rgba(128,128,0,0.5)">
In JavaScript, set an Event Listener when the window is loaded:
window.addEventListener('load', function() {
//set the image's dimensions to the divs that need it
var imageDiv = document.getElementById("some-id");
var otherDiv = document.getElementById("other-div");
otherDiv.style.height = imageDiv.offsetHeight + "px";
otherDiv.style.width = imageDiv.offsetWidth + "px";
});

CSS - fixed element width set to specific internal content?

Is it possible to fix the width (or min-width) of an element equal to when that element is filled with specific content?
Example: a button for selecting the month can have text of January, February, etc. I would like the button to always be the width as if the text is September (the longest string, visually). What happens currently, is the button is very small if the current selection is May or July, then much larger when the selection is November or September, and further, this can change the layout of other elements.
Of course I could set width or min-width using pixels, or a percentage, or vw, etc -- but given the breadth of devices, screens, user control over zoom or font sizes, the only safe way is to guess at a size that is likely far larger than actually necessary, which itself looks bad and is undesirable.
Setting a sibling div with visibility: hidden is the key, both of which reside inside another container div.
Codepen here: https://codepen.io/anon/pen/XQxeep
let strings = [
'tiny', 'short', 'medium-length', 'this is a long string',
'finally, an extremely long string'
];
let m = 0;
function nextString() {
m = (m == 4) ? 0 : m + 1;
document.getElementById('bt').innerHTML=strings[m]
}
button {
display: inline-block;
position: relative;
}
.showme {
position: absolute;
left: 0px;
right: 0px;
}
.hideme {
visibility: hidden;
}
this is the button we are trying to keep a fixed size, the size of the longest element so it will not expand:
<button onclick="nextString()">
<div class="outer">
<div class="showme" id="bt">tiny</div>
<div class="hideme">finally, an extremely long string</div>
</div>
</button>

CSS Fixed Header, scrolling body with left sidbar/content/right sidbar and footer

I have spent the last week trying to tweak a layout and keep rebuilding from scratch without success, so asking for help.
I'm trying to achieve
1. a fixed header which does not scroll and always viewable
2. a main area with left sidebar (nav) / content / right sidebar (ads) which scroll
3. a footer which is only visible when scrolled to the bottom
My vision is :
|--------------------------------|
| header (always viewable ) |
|--------------------------------|
|| L | | R ||
|| e | | i ||
|| f | | g ||
|| t | | h ||
|| | | t ||
|| S | Content Area | ||
|| i | | S ||
|| d | | i ||
|| e | | d ||
|| b | | e ||
|| a | | b ||
|| r | | a ||
|| | | r ||
||------------------------------||
|| footer visible at end scroll ||
||------------------------------||
The basic structure of the HTML has a few more divs than could be done with but I'm planning for maximum flexibility ( and problably creating problems)
<div class="site-container">
<div class="site-header">
SITE HEADER
<!-- HEADER CONTENT GOES HERE -->
</div> <!-- site-header -->
<div class="site-content">
SITE-CONTENT (with reduced padding not visible )
<div class="content-main">
<div class="content-main-left">
CONTENT-MAIN-LEFT ( Navigation )
</div>
<div class="content-main-middle">
CONTENT-MAIN
<!-- MIDDLE COLUMN CONTENT GOES HERE -->
Lorem ipsum dolor etc ...
</div>
<div class="content-main-right">
CONTENT-MAIN-RIGHT ( Ads )
</div>
<div class="content-footer">
CONTENT-FOOTER
</div>
</div> <!-- content-main -->
</div> <!-- site-content -->
</div> <!-- site-container -->
However, the more I play with it, the more messy and unworkable it gets.
I'm currently stuck in the loop of fixing one problem while creating another.
Here's my JSFiddle version
Any help is greatly appreciated.
Thanks
You'll want to work out how you want that central column of text to work.
If you have a fixed width container, you could float the elements, and give them a fixed width.
Many grid systems like Bootstrap or Base use floated columns to lay things out. They also use media queries in CSS to cater for different screen sizes.
If you want a layout that has fixed-width columns and a variable width central column, and you did want to do things yourself, you can position things absolutely inside your main content holder.
Check out an updated JSFiddle to see how you could use position:absolute to lay things out.
There's a few updates to your HTML in there, but a CSS layout like this:
.site-header {
position: fixed;
top:0px;
width: 100%;
height: 50px;
padding:20px 0;
z-index:2;
}
.content-main-left {
width:100px;
min-height:200px;
position:absolute;
left:0;
background-color: tan;
}
.content-main {
padding:0 120px 0 120px; /* padding to make room for the left and rigth columns */
}
.content-main-right {
width:100px;
min-height:200px;
position:absolute;
right:0;
top:0;
background-color: rosybrown;
}
.site-content {
position:relative;
top:120px;
}
.content-footer {
position: relative;
left:0;
height: 60px;
width: 100%;
}
It's always good to strip things back and get one thing working at a time. There were a few lines in that probably weren't helping:
The left column <div> wasn't closed, so your main content was sitting inside that <div>
It looks like you've tried to close the 'site-header' tag at the bottom of the content.
Putting a <div> around your left, center and right columns will help you place a footer at the bottom of all three sections. I've renamed this "site-footer"
Hope this helps!
I found, that if my left / right sidebars grow in length then the bottom of the page starts to get messy.
i.e. jsFiddle
I spent a lot of time playing around but couldn't get it working.
I did not know about the calc option, which I think enables me to have an easier to manage (for a CSS noob like me) solution as I can stay away from absolute positioning.
The result is jsFiddle.
I'd love the option of getting the left/right bars to grow to the bottom using something like
height: calc(100% - 100);
but it doesn't seem to work, and presumably I'd have to delve back into the world of absolute to get it to work.
Again, thanks for the help.

Allowing images to shrink, but not stretch

I have a site with 4,000+ pages and 10 or more jpeg images per page, of varying sizes. I'm trying to make the site more mobile friendly. To that end, i want to make it possible for the images to shrink to fit on smaller screens. I know that i can do something like this to signal that the images can shrink:
img.bodyImg
{
width: 100%;
max-width: 357px;
height: auto;
}
But what if not all images have a width of 357 (or whatever), and i don't want smaller images stretched beyond their true dimensions? And just to make things more fun, what if the images tags don't have height and width attributes specified?
My goal is to find a solution that doesn't require me to adjust tens of thousands of image calls manually, but i can do a search and replace. Images are currently wrapped in a div container and have a class, like so:
<div class="imgDiv"><img class="bodyImg" src="http://www.example.com/image.jpg"></div>
I'm also open to the possibility that i'm going about this in the wrong way entirely.
Using max-width is simple, effective, and requires no JavaScript.
The CSS below creates responsive images that shrink to fit the container's width but won't expand beyond their native sizes.
img.bodyImg {
max-width:100%
}
In the demonstration below, both images are 300px X 75px. The first container is 200px wide and the second one is 400px wide. Notice that the first image shrinks to fit in the container, but the second image does not expand beyond its native size. Also note that the proportions of each image remain accurate.
div {
background-color: #CCC;
margin:0 0 .5em;
padding:.25em;
}
div.one {
width: 200px;
}
div.two {
width: 400px;
}
img {
display:block;
max-width: 100%;
}
<div class="one">
<img src="http://lorempixel.com/300/75/abstract/4/" />
</div>
<div class="two">
<img src="http://lorempixel.com/300/75/abstract/4/" />
</div>
Additional Notes
I've included display:block to remove the descender space below the image.
If your images have specific height and width attributes (as they arguably should), you can add height:auto and/or width:auto to override those attributes.
Bootstrap uses this method for responsive images.
You can use a little jQuery to figure out each image's native width, and set perscriptive max-widths for each image afterward:
$('.bodyImg').each(function() {
// Create new offscreen image to test
var theImage = new Image();
theImage.src = $(this).attr("src");
// Get accurate measurements from that.
var imageWidth = theImage.width;
$(this).css({
"max-width" : imageWidth
});
}
UPDATE: And if you want each image to have a uniform width, you can store the smallest max width and apply it to all of the images:
var smallMax;
$('.bodyImg').each(function() {
// Create new offscreen image to test
var theImage = new Image();
theImage.src = $(this).attr("src");
// Get accurate measurements from that.
var imageWidth = theImage.width;
// if the variable exists and is bigger than
// the current width, use the new max width
if (smallMax !== undefined && smallMax > imageWidth) {
smallMax = imageWidth;
}
// set the variable if it hasn't been set yet
else if (smallMax == undefined) {
smallMax = imageWidth;
}
// keep the old variable if it is defined and smaller
else {}
$(this).css({
"max-width" : smallMax
});
}
Why not just:
max-width:100%; /*Ensure the width scales to the width of the parent container*/
width:auto; /* Not required, but sometimes is nice to ensure the width not being overridden by other factors like browser quirks */
height: auto; /*Ensure the image keeps its ratio*/
Try using max-width:100% and height: auto in your css. If you want to make your site mobile friendly I would suggest looking into bootstrap framework for more flexibility.

Getting the larger of two divs floated side-by-side to extend its border?

I have two <div>s which look like this:
---------------------------
| | |
| DIV 1 | DIV 2 |
| | |
---------------------------
The first div is floated left, while the second div is floated right. The left div has a right border, while the second div has a left border.
I would like the larger of these divs to extend its border all the way to the bottom of their container and I want only one border.
How could I achieve this?
Any help would be greatly appreciated.
Use jQuery
add this in head
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.6.4/jquery.min.js"></script>
and put this snippet in head or body.
<script type="text/javascript">
$(document).ready(function() {
var large=$(div).eq(0), small = $(div).eq(1), temp;
if(large.height()<small.height()) {
temp = large;
large = small;
small = temp;
}
large.css('border-right','1px solid black');
small.css('border-left', '0px');
});
</script>
Do you mean that you want the larger div to be the full height of the container? If that's what you mean, you can specify the height to be 100% in the css for the larger div.
One way to achieve this effect is via absolute positioning. In this method, the width of your container is known (like 1024px for example) and you divide the available space between your two divs, 324px for the your div2 and 700px for div1. This way, you don't have to float divs. All you have to do is to define position: relative; for the container, and position: absolute; for two divs. Then you have to specify
top: 0;
right: 324px;
bottom: 0;
left: 0;
for your div1.
Another method is the floating that you've used here. By floating, you should float your both divs to the left or right, and specify width for each of them. Then you should not worry about the height of the width, because the div1 would be extended based on its contents.
if you mean that div one is higher then div 2 and you want them to be the same height then this is the script for you.
function setHeight(id1, id2){
//haal de elementen op en plaats deze in een lokale variabel
var elem1 = document.getElementById(id1);
var elem2 = document.getElementById(id2);
// controleer of de offsetHeight van element1 of 2 groter is
// dan de ander en pas de kleinste aan
if(elem1.offsetHeight>elem2.offsetHeight){
elem2.style.height = elem1.offsetHeight+'px';
}else{
elem1.style.height = elem2.offsetHeight+'px';
}
}
put this in a javascript file or in the head of your html inside de script tags ofcourse and put the following code inside your body tag
onload="setHeight(id1, id2)"
now you just need to give the div's you want to resize the id1 and 2(can be any name, as long as its is there in the parameters) and it works :)
good luck,
and let me know if you have isues. i use this myself so it works :)