I want to rotate the image, but it is going out of parent div.
<div>
<img src="https://cdn.eso.org/images/thumb300y/eso1907a.jpg">
<button class="rotate-button">rotate image</button>
</div>
jquery code
$('.rotate-button').on('click', function() {
var image = $(this).prev('img');
image.className = "rotated_90deg";
});
unrotated state:
rotated state:
how can I keep the image smaller in rotated state, so that it does not go out of parent div?
Try using the solution with scale property
$('.rotate-button').on('click', function() {
var image = $(this).prev('img');
image.className = "rotated_90deg";
});
.rotated_90deg {
transform: rotate(90deg) scale(0.5, 1);
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div>
<img src="https://cdn.eso.org/images/thumb300y/eso1907a.jpg">
<button class="rotate-button">rotate image</button>
</div>
"tranform rotate" does just that. It retains its original height, and the forging is done in a separate visual layer.
the best thing you can do is set the height of the area where the image rotates equal to the largest side of the image
const img = document.querySelector('img');
const {offsetHeight, offsetWidth} = img;
if(offsetWidth >= offsetHeight) {
img.parentElement.style.height = offsetWidth + 'px';
}
const rotations = [];
const rotateImage = () => {
rotations.push('rotate(45deg)');
img.style.transform = rotations.join(' ');
}
div { display: flex; }
img { transition: .3s; margin: auto; }
button { display: block; margin: auto; position: relative }
<div>
<img src="http://placekitten.com/300/200">
</div>
<button onclick=rotateImage()>Rotate</button>
hmm ... maybe I hastened to answer.
As a solution, "position: relative;" on the button
Put the image inside a container div, give it an id or class and set the overflow to hidden:
.imgContainer{
overflow: hidden;
}
Or if you want the picture to scale so it fits within the div, set max width and height:
.imgContainer img{
max-width: 100%;
max-height: 100%;
}
Related
I am currently developing a plugin for existing websites.
Its purpose is to display a sidebar with my content. To that end, the website owner creates an empty div, references my javascript file and calls my code with the ID of the empty div.
My plugin is then creating an iFrame in that empty div and loads its content. It also is responsible for styling the provided div so that it actually is a sidebar: It changes the width and height of that div and attaches it to the right edge of the screen.
So, all of that is basically working - loading my iFrame and styling the div.
The problem is that I am not satisfied with the result.
I have tried two different styles for the div:
Approach 1: float right
I used this CSS:
float: right;
height: 100%;
width: 100px;
The problem with this is that it doesn't change the total width of the rest of the page. In other words, elements on the website with a width: 100% will be shown below my sidebar.
https://jsfiddle.net/DHilgarth/mmzefm14/
Approach 2: Absolute positioning
I used this CSS:
position: absolute;
top: 0;
right: 0;
height: 100%;
width: 100px;
This approach has the problem that my sidebar now simply overlaps the controls from the website.
https://jsfiddle.net/DHilgarth/34hmnw9h/1/
Is there a way to achieve what I want? A sidebar that basically reduces the available size of the body for all elements, except mine?
I have now chosen to actually do exactly what I asked for: I reduce the available width of the body tag.
This is not trivial because of box-sizing, padding, margin, border etc and I am sure I have missed a lot of edge cases but for now, the following logic is working for me:
If box-sizing is border-box: set the right padding of the body element to the width of my sidebar.
Otherwise, set the width of the body element to the width of the body element minus the width of the sidebar. On resize of the window, the width of the body has to be adjusted accordingly.
Code:
function initSidebar() {
loadSidebar("sidebar");
}
// This code would be loaded from a javascript file I provide
function css(element, property) {
return window.getComputedStyle(element, null).getPropertyValue(property);
}
function getSidebarWidth(sidebarElement) {
var boundingRect = sidebarElement.getBoundingClientRect();
return boundingRect.right - boundingRect.left;
}
function styleBorderBoxBody(bodyElement, sidebarElement) {
bodyElement.style.paddingRight = getSidebarWidth(sidebarElement) + "px";
}
function resizeBody(bodyElement, previousWindowWidth, previousBodyWidth) {
var currentWindowWidth = window.innerWidth;
var newBodyWidth = previousBodyWidth - previousWindowWidth + currentWindowWidth;
bodyElement.style.width = newBodyWidth + "px";
return {currentWindowWidth, newBodyWidth};
}
function styleBody(bodyElement, sidebarElement) {
var boxSizing = css(bodyElement, "box-sizing");
if(boxSizing == "content-box" || !boxSizing || boxSizing == "") {
var sidebarWidth = getSidebarWidth(sidebarElement);
var width = bodyElement.clientWidth - sidebarWidth;
bodyElement.style.width = width + "px";
sidebarElement.style.right = (-sidebarWidth) + "px";
var windowWidth = window.innerWidth;
window.addEventListener("resize", function(e) {
var newWidths = resizeBody(bodyElement, windowWidth, width);
width = newWidths.newBodyWidth;
windowWidth = newWidths.currentWindowWidth;
});
} else if(boxSizing == "border-box") {
styleBorderBoxBody(bodyElement, sidebarElement);
window.addEventListener("resize", function(e) { styleBorderBoxBody(bodyElement, sidebarElement); });
}
}
function loadSidebar(sidebarId) {
var sidebarElement = document.getElementById(sidebarId);
sidebarElement.className = "sidebar";
var bodyElement = document.getElementsByTagName("body")[0];
styleBody(bodyElement, sidebarElement);
}
// end: my code
initSidebar();
* {
margin: 0;
padding: 0;
}
html {
}
*,
*:before,
*:after {
box-sizing: inherit;
}
body {
font: 14px/1.1 Helvetica, Sans-Serif;
position: absolute;
left: 0;
right: 0;
top: 0;
bottom: 0;
height: 100%;
}
#editor {
width: 100%;
height: 500px;
}
/* this class would be loaded from a CSS file I provide */
.sidebar {
border-color: green;
border-style: solid;
position: fixed;
top: 0;
right: 0;
bottom: 0;
width: 100px;
}
<div id="sidebar"></div>
<h1>Some UI from the existing website</h1>
<textarea id="editor">The text area</textarea>
I'm working on a site where users can manipulate an SVG image through a couple of textboxes.
I would like to have the SVG scale to fit the container div.
For example, if the SVG was exactly the container's height and 10 pixels wide, then doubling the height would cause the apparent width to be 5 pixels.
My page is split roughly in half, with the numbers on the left and the image on the right. Resizing the browser thus causes the SVG's container element to change shape, meaning that I can't hardcode the container's dimensions in the SVG.
Every solution I've found online uses the viewBox attribute; however, I can't find a way to apply that without having a hard-coded container size.
Here is a fiddle with my editor setup:
https://jsfiddle.net/xyjs5b63/
Adjusting viewBox sounds like what you want. I'm not sure what you were doing that made it not work.
var svg = document.querySelector('svg');
var inputs = document.querySelectorAll('input');
var height_elem = inputs[0];
var width_elem = inputs[1];
height_elem.value = '100';
width_elem.value = '100';
height_elem.addEventListener("change", valueChange);
width_elem.addEventListener("change", valueChange);
function valueChange() {
svg.setAttribute('viewBox', "0 0 "+width_elem.value+" "+height_elem.value);
}
valueChange();
#out {
width: 100px;
height: 100px;
background-color: honeydew;
}
svg {
width: 100%;
height: 100%;
}
<div id="main">
<div id="in">
<input type="number"><br>
<input type="number">
</div>
<div id="out">
<svg>
<rect width="100%" height="100%"></rect>
</svg>
</div>
</div>
var rect = document.querySelector('rect');
var svg = document.querySelector('svg');
var inputs = document.querySelectorAll('input');
var height_elem = inputs[0];
var width_elem = inputs[1];
height_elem.value = '100';
width_elem.value = '100';
height_elem.addEventListener("change", valueChange);
width_elem.addEventListener("change", valueChange);
function valueChange() {
max = parseInt(height_elem.value) >= parseInt(width_elem.value) ? 'h' : 'w';
if (max == 'h') {
rect.setAttribute('height', "100%");
rect.setAttribute('width', (width_elem.value * 100 / height_elem.value)+"%");
}
else {
rect.setAttribute('width', "100%");
rect.setAttribute('height', (height_elem.value * 100 / width_elem.value)+"%");
}
}
valueChange();
#main {
width: 100%;
padding: 0;
}
#in {
float: left;
width: 40%;
height: 100%
}
#out {
margin: 10%;
width: 20vw;
height: 20vw;
}
svg {
width: 100%;
height: 100%;
}
<div id="main">
<div id="in">
Height: <input type="number"><br>
Width: <input type="number">
</div>
<br>
<div id="out">
<svg height="auto">
<rect></rect></svg>
</div>
</div>
Does this solve your problem?
The site below uses a fixed background-image in each section, but how do I add fixed content (text, images) to each sections and keep the same scrolling effect?
http://tympanus.net/Blueprints/ScrollingLayout/
Have a look at my example to get a better idea of what I want:
http://jsfiddle.net/w919y0gb/
My try:
#wrapper {
position: relative;
height: 500px;
width: 500px;
overflow: scroll;
}
.section {
position: relative;
height: 100%;
width: 100%;
}
.content {
position: fixed;
}
#s1 {
background-color: #f00;
}
#s2 {
background-color: #0f0;
}
#s3 {
background-color: #00f;
}
#s1 .content {
}
#s2 .content {
margin-top: -400px;
}
#s3 .content {
margin-top: -800px;
}
<div id="wrapper">
<div class="section" id="s1">
<div class="content">hello1</div>
</div>
<div class="section" id="s2">
<div class="content">hello2</div>
</div>
<div class="section" id="s3">
<div class="content">hello3</div>
</div>
</div>
What I want:
The first section (red) should only display "hello1"
The second (green) only "hello2"
The third (blue) only "hello3"
something like this maybe? little hacky, but does the trick if you have set section heights:
$(document).ready(function(){
$('.div3').hide();
$('.div2').hide();
$('.div1').show();
$('#wrapper').scroll(function(){
console.log($('#wrapper').scrollTop());
if($('#wrapper').scrollTop() > 945){
$('.div3').show();
$('.div2').hide();
$('.div1').hide();
}
else if ($('#wrapper').scrollTop() > 465) {
$('.div3').hide();
$('.div2').show();
$('.div1').hide();
}
else {
$('.div3').hide();
$('.div2').hide();
$('.div1').show();
}
});
});
updated fiddle: http://jsfiddle.net/w919y0gb/3/
with this, you could also modify the placement of the "hello1/hello2/hello3" to be in the same position instead of in different places. or you could just have one div in which you modify/replace the text from hello1/hello2/hello3 depending on the scroll position. hope this helps!
That reference site is simply using a background-image set to fixed like so:
FIDDLE
UPDATE
Ok I understand. You would need to do something like this with jquery and $(window).scroll() function:
NEW FIDDLE
using positon: fixed just breaks the element out of the flow of the document and it can't be contained by a parent so you need to use absolute and position it based on the scrollTop to give the appearance that it's fixed.
You could also set the height of your webpage, and then make divs appear as you scroll up or down.
Heres a working example: http://jsfiddle.net/ZyKar/1738/
$(document).scroll(function () {
var y = $(this).scrollTop();
if (y > 0 && y < 400) {
$('#s1').fadeIn();
$('#s3').fadeOut();
$('#s2').fadeOut();
} else if (y > 400 && y < 800) {
$('#s1').fadeOut();
$('#s2').fadeIn();
$('#s3').fadeOut();
}else if (y > 800) {
$('#s3').fadeIn();
$('#s2').fadeOut();
}
});
After you scroll a certain amount of pixels, divs will begin to appear and replace each other.
You may alter the value of y by setting the height of your body in css, as shown in the fiddle. You can then set the pixels conditions in the jQuery to whatever you like.
If I have an image on html page, can I use html or css do the following?
When width of the image is greater than height, set height to a fixed value and auto stretch width; when height is greater than width, set width and auto stretch height?
Thanks a lot!
No, this is not possible - conditional statements cannot be handled with HTML or CSS, but you have to do it with JS.
An example would be calculating (and perhaps storing for future use) the aspect ratio of an image to determine whether is it in landscape or portrait mode:
$(document).ready(function() {
$("img").each(function() {
// Calculate aspect ratio and store it in HTML data- attribute
var aspectRatio = $(this).width()/$(this).height();
$(this).data("aspect-ratio", aspectRatio);
// Conditional statement
if(aspectRatio > 1) {
// Image is landscape
$(this).css({
width: "100%",
height: "auto"
});
} else if (aspectRatio < 1) {
// Image is portrait
$(this).css({
maxWidth: "100%"
});
} else {
// Image is square
$(this).css({
maxWidth: "100%",
height: "auto"
});
}
});
});
See fiddle here - http://jsfiddle.net/teddyrised/PkgJG/
2019 update: As ES6 is becoming the defacto standard, the above jQuery code can be easily refactored into vanilla JS:
const images = document.querySelectorAll('img');
Array.from(images).forEach(image => {
image.addEventListener('load', () => fitImage(image));
if (image.complete && image.naturalWidth !== 0)
fitImage(image);
});
function fitImage(image) {
const aspectRatio = image.naturalWidth / image.naturalHeight;
// If image is landscape
if (aspectRatio > 1) {
image.style.width = '100%';
image.style.height = 'auto';
}
// If image is portrait
else if (aspectRatio < 1) {
image.style.width = 'auto';
image.style.maxHeight = '100%';
}
// Otherwise, image is square
else {
image.style.maxWidth = '100%';
image.style.height = 'auto';
}
}
div.wrapper {
background-color: #999;
border: 1px solid #333;
float: left;
margin: 10px;
width: 200px;
height: 250px;
}
<div class="wrapper">
<img src="http://placehold.it/500x350" />
</div>
<div class="wrapper">
<img src="http://placehold.it/350x500" />
</div>
<div class="wrapper">
<img src="http://placehold.it/500x500" />
</div>
However, if all you want is to ensure the image fits within an arbitrary sized container, using simple CSS will work:
div.wrapper {
background-color: #999;
border: 1px solid #333;
float: left;
margin: 10px;
width: 400px;
height: 400px;
}
div.wrapper img {
width: auto
height: auto;
max-width: 100%;
max-height: 100%;
}
<div class="wrapper">
<img src="http://placehold.it/500x350" />
</div>
<div class="wrapper">
<img src="http://placehold.it/350x500" />
</div>
<div class="wrapper">
<img src="http://placehold.it/500x500" />
</div>
As I can have a div with two children inside, one of which is not shown (display: none) and the other occupies the entire space of the father, but when I tell javascript to display the hidden the other autoredimensiones to space left without using javascript?
html:
<div class="parent">
<div class="child1" id="id1">
</div>
<div class="child2">
</div>
</div>
css:
.parent {
height: 200px;
background-color: red;
}
.child2 {
height: 100%;
background-color: blue;
}
.child1 {
display:none;
height: 50px;
background-color: green;
}
javascript:
var myDiv = document.getElementById('id1');
myDiv.style.display="block";
This can't be achieved with pure CSS, but if you're okay about adding a little more JavaScript (in order to add a class-name), then it can be achieved:
Amended JavaScript:
var myDiv = document.getElementById('id1');
myDiv.style.display = "block";
myDiv.className += ' nowShown';
Appended CSS:
.child1.nowShown {
float: left;
width: 50%;
}
.child1.nowShown + .child2 {
display: inline-block;
width: 50%;
}
JS Fiddle proof-of-concept.
Otherwise it's not possible, simply because CSS lacks the capacity to determine the visual/display state of an element. If it had a :visible pseudo-class then it'd be possible, but without such, as currently, it's sadly not.
Adapted the above proof-of-concept to implement a slightly less-than-concise toggle:
function showDiv1() {
var myDiv = document.getElementById('id1'),
cN = myDiv.className;
myDiv.style.display = "block";
if (cN.match(/nowShown/)){
myDiv.className = cN.replace(/nowShown/,'');
myDiv.style.display = 'none';
}
else {
myDiv.className += ' nowShown';
}
nC = myDiv.className;
myDiv.className = nC.replace(/\s{2,}/,' ');
}
document.getElementsByTagName('button')[0].onclick = function(){
showDiv1();
};
JS Fiddle demo.