Skip hidden element on :first-child selector - javascript

I'm using Sortable.js and I'm having the following problem:
I have a list of items that I want to sort, and I need the first element to be wider than all 3 others.
In order to do this, I have the following css:
#produto_img {
display: -webkit-box;
display: -ms-flexbox;
display: flex;
-ms-flex-wrap: wrap;
flex-wrap: wrap;
}
#produto_img > li {
height: 100px;
margin: 0 5px;
}
#produto_img > li:not(:first-child) {
flex: 1;
}
#produto_img > li:first-child {
width: 100%;
height: 200px;
margin-bottom: 10px;
}
It works fine when I start dragging any item after the first, even if I switch with the first item it works fine.
It creates the following markup:
But when I start dragging from the first, I'll lose the styling because the plugin creates another item on its place and sets it to display: none, so the :first-child selector won't work anymore, and it loses the styling.
This gif shows what's happening.
My first tought would be to somehow skip the first-element if it is display: none, or use something like :first-child:visible, but this isn't working, obviously.
Is there any workaround?

Sadly the :visible pseudoclass is still distinct to jQuery. A workaround you can use though would be to handle the hiding by adding/removing a class.
Then it's a matter of overrides
li.hidden {
display: none;
}
li:not(.hidden) {
width: 100%;
height: 200px;
margin-bottom: 10px;
}
li:not(.hidden) ~ li {
width: auto;
height: auto;
margin-bottom: 0;
flex: 1;
}

Related

How to keep all the elements within container using flexbox?

I'm trying to get all the letters displayed within container evenly spaced out using flexbox. Right now, if I enter sentence like "I like learning code", all elements are displayed within container and works ok, but if I use long word like "refrigerator", letters comes out of container. But I'm trying to keep all the letters to stay within container no matter how long the word is. I tried all the available flexbox techniques, but no luck. Tried max-width on container too. What am I missing? Here is the code in code sandbox: https://codesandbox.io/s/modern-sun-3u7b3?file=/src/App.js
import React from "react";
import "./styles.css";
function App() {
// let sentence = "I like learning code";
let sentence = "refrigerator";
const words = sentence.split(" ");
return (
<div className="pageContainer">
{words.map((word, i) => (
<div className="row" key={i}>
{[...word].map((letter) => (
<p className="letterBorder">{letter}</p>
))}
{i === words.length - 1 ? null : <p className="whiteSpaceBorder"></p>}
</div>
))}
</div>
);
}
export default App;
.letterBorder {
border: 25px;
background: grey;
padding: 20px;
width: 50px;
height: 30px;
flex-grow: 1;
margin-right: 4px;
margin-left: 4px;
}
.row {
display: flex;
justify-content: space-evenly;
min-width: 100%;
align-content: flex-start;
}
.whiteSpaceBorder {
border: 25px;
background: orange;
padding: 20px;
width: 50px;
height: 30px;
flex-grow: 1;
margin-right: 4px;
margin-left: 4px;
}
.pageContainer {
border-radius: 1rem;
text-align: center;
background: lightcyan;
height: 40rem;
width: 30rem;
margin: auto;
}
Your error is due to the hardcoded horizontal padding of your letterBorder class.
Replace
padding: 20px;
with
padding: 20px 0;
https://codesandbox.io/s/gracious-violet-qg1xt?file=/src/App.js
This is where the css property flex-wrap comes in handy. Flexbox items all try to fit into one line by default. However, you can make them wrap using flex-wrap: wrap.
Add it to your row class:
.row {
display: flex;
flex-wrap: wrap; /* Allow items in row to "wrap" to next line if needed */
justify-content: space-evenly;
min-width: 100%;
align-content: flex-start;
}
See this css-tricks page for a better visual explanation.

centering images by HTML / JS

I'm trying to center an image on Qualtrics. I tried a lot of codes I found, but nothing works.
Examples of what I already tried:
<style>
.img-container {
text-align: center;
display: block;
}
</style>
.center {
display: block;
margin-left: auto;
margin-right: auto;
}
<style>
.ChoiceStructure {
text-align: center;
}
</style>
The preference is to use HTML or JavaScript rather than CSS because the center is for a specific question.
In the question, the URL of the images appears in LOOP & MERGE so I do not have the specific name of the image to write in the code.
Any suggestions?
Thanks a lot!
The simplified example below uses flex and justify-content.
In your case, it's not div but .img-container that you probably need to use for the container.
The span style rule is just a simple example and you don't need that at all.
div {
display: flex;
justify-content: center;
}
span {
background-color: aqua;
width: 300px;
height: 300px;
}
<div>
<span></span>
</div>
So, in your case it should be:
.img-container {
display: flex;
justify-content: center;
}

Vertical align text dynamically

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;
}

When using (flexlayout) column, div isn't correct size

I have 4 li's with a div having a background image (through CSS). I'm using flexbox for the layout. I want it to have columns with 3 li's in each column. Everything is working fine besides for the div containing image. The height of the div is larger than its parent.
The weird thing is, when I make it into rows instead of columns, it has the correct height.
(If it shows the correct size by you, then try making the windows width wider.)
How can I make the div to have the correct size?
JSFiddle
$(document).ready(function () {
"use strict";
function resizeHeightLi() {
$('li').css('height', 'calc(' + $('li').width() + 'px / 1.8)');
}
resizeHeightLi();
$(window).resize(function () {
resizeHeightLi();
});
});
html, body {
margin: 0;
height: 100%;
}
div {
align-items: center;
justify-content: center;
height: 100%;
display: flex;
overflow: auto;
background-color:aqua;
}
ul {
margin-top: auto;
margin-bottom: auto;
flex-basis: 70%;
height: 80%;
padding: 0;
display: inline-flex;
flex-wrap: wrap;
/*flex-direction: row; // When it's set to row, it works fine.*/
flex-direction: column;
}
li {
flex-basis: calc(100% / 3 - 2px); /* Subtract the border */
color: firebrick;
list-style-type: none;
border: 1px solid firebrick;
}
.image {
background-image: url("http://i.imgur.com/nswXRR4.jpg");
background-size: contain;
background-repeat: no-repeat;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div>
<ul>
<li><div class="image"><span>1</span></li>
<li><div class="image"><span>2</span></li>
<li><div class="image"><span>3</span></li>
<li><div class="image"><span>4</span></li>
</ul>
</div>
Since the height of each li is taken care of by your flex-basis rule in the CSS, I think there is no need to assign the height again with JavaScript. Instead, you can get the height of each li after the flex calculations are done and assign it to your image divs. That way, both parent and child elements are the same height.
function resizeHeightLi() {
$('.image').css('height', $('li').height() + 'px');
}
EDIT (CSS Only)
To accomplish the same purely with CSS, you can delete all the JS you have now and add the following to your CSS:
// In addition to what you already have in your li
li {
// ...
position: relative;
}
// Same here, in addition to what you have in .image
.image {
// ...
position: absolute;
width: 100%;
height: 100%;
}

Calculate row height in CSS grid with JavaScript

I made a small CSS grid framework for my new project but soon after, I have realized it has some shortcomings. Problem is, columns don't occupy whole height of a row which in turn prevents me from creating "blocky" layout and with current setup I can't achieve this with CSS.
I have solved this with some JavaScript, but what troubles me is that this peace of code needs to be executed after the page loads. Which means layout will be a bit messy if there's a lot of content to load.
Also, I'm not great with JavaScript so I'm not sure if I did this properly.
Here's link to source code on CodePen
[NOTE]
I don't want to use any JavaScript libraries
You can try using css table display property stack and use javascript as a fallback to unsupported browsers if required.
display: table;
display: table-cell;
display: table-column;
display: table-colgroup;
display: table-header-group;
display: table-row-group;
display: table-footer-group;
display: table-row;
display: table-caption;
http://codepen.io/anon/pen/LEniv
Browser compatibility
http://jsfiddle.net/cDZpA/
.container {
position: relative;
font-size: 0px;
overflow: hidden;
}
.col {
display: inline-block;
width: 33.333%;
font-size: 14px;
vertical-align: top;
height: 100%;
position: relative;
margin-bottom: -10000px;
padding-bottom: 10000px;
}
.c1 { background: yellow; }
.c2 { background: purple; }
.c3 { background: red; }
Don't ask me how, but this code I've put down works.
Here your CodePen fixed:
http://codepen.io/anon/pen/wkbrj

Categories