Is it possible to repeat one div several times in flex? - css

I am trying to create some windows on a house, this house has 30 windows. I wondered if it would be possible to create it using only one div and repeating it?

Good Morning! With CSS only you cant make it generic. CSS in combination with JS will help you to archive this goal. Take a look to the example below:
const h = document.querySelector('.h');
const wc = 30;
for(let i = 0; i < wc; i++) {
const w = document.createElement('div');
h.append(w);
}
.h {
background-color: brown;
display: flex;
gap: 10px;
width: 500px;
flex-wrap: wrap;
padding:10px;
}
.h div {
background-color: lightblue;
height: 50px;
width: 50px;
}
.h div:after {
content: ' ';
}
<div class="h"></div>

Related

Styling borders of css grid with fexible number of rows and columns [duplicate]

I'd like to use the CSS border attribute to make a fine 1px grid between span elements, like so.
|
1 | 2
-----|-----
3 | 4
|
This is what I currently have. It doesn't quite work obviously.
<html>
<head>
<style>
div {
width: 204px;
}
span {
display: inline-block;
height: 100px;
width: 100px;
border: 1px solid #ccc;
border-left-width: 0;
border-top-width: 0;
}
</style>
</head>
<body>
<div><span>1</span><span>2</span><span>3</span><span>4</span></div>
</body>
</html>
When the div is set to 306px and the elements reflow, the solution should adapt dynamically.
| |
1 | 2 | 3
-----|-----|-----
4 |
|
Preferably CSS only, or pure Javascript. Older browsers like IE7 can be ignored.
I came up with this approach, which I think works pretty well with minimal CSS and hacks: https://codepen.io/eriklharper/pen/JMKMqa
.border {
background-color: gray;
}
.grid {
display: grid;
grid-template-columns: repeat(2, minmax(auto, auto));
grid-gap: 1px;
}
.grid > div {
background-color: white;
padding: 10px;
}
<div class="border">
<div class="grid">
<div>Item 1</div>
<div>Item 2</div>
<div>Item 3</div>
<div>Item 4</div>
</div>
</div>
It introduces an extra wrapping element around the whole grid (which isn't perfect either) but I've found this to be a worthwhile compromise, despite. The lack of ability to simply style the grid-gaps directly is a shortcoming with CSS Grid that should be addressed with the spec.
1. HTML+CSS solution
HTML:
<div>
<i></i>
<span>1</span>
<span>2</span>
<span>3</span>
<span>4</span>
<i></i>
</div>​
CSS:
div {
position: relative;
width: 202px; /* or 303px (or 100px * n + n) */
font-size: 0;
}
span {
display: inline-block;
height: 100px;
width: 100px;
border: 1px solid #ccc;
border-left-width: 0;
border-top-width: 0;
font-size: 12px;
}
i {
position: absolute;
background: #fff;
height: 1px;
bottom: 0;
left: 0;
width: inherit;
}
​i:first-child {
height: auto;
width: 1px;
top: 0;
left: auto;
right: 0;
}​
DEMO: http://jsfiddle.net/HTgKJ/
2. HTML+CSS+JavaScript solution
HTML+CSS:
<!-- See approach 1. -->
JavaScript:
var block = document.querySelectorAll(".block");
for (var i = 0; i < block.length; i++) {
var spanWidth = block[i].querySelector("span").clientWidth,
n = Math.floor(block[i].clientWidth / spanWidth);
block[i].querySelector("i:first-child").style.left =
(n * spanWidth + (n - 1)) + "px";
}​
DEMO: http://jsfiddle.net/HTgKJ/1/
I'm using this solution, which automatically sets the border.
http://jsfiddle.net/aLz2T/3/
HTML
<div><span>1</span><span>2</span><span>3</span><span>4</span></div>​
CSS
div {
width: 204px; /* adjust to get less/more columns */
}
span {
display: inline-block;
height: 100px;
width: 100px;
border: 1px solid #ccc;
border-left-width: 0;
border-top-width: 0;
}​
JavaScript
var a = document.querySelector('div');
// columns
var b = parseInt(a.offsetWidth / (100 + 2), 10);
for(var c, d = document.querySelectorAll('span'), e = d.length, i = 0; c = d[i]; i++) {
// column
c.style.borderRightWidth = ((i + 1) % b) != 0 ? "1px" : "0";
// row
c.style.borderBottomWidth = parseInt(i / b, 10) * b < e - b ? "1px" : "0";
}​
Make the background color of the containing element the color you want for the border.
Make the background color of the elements within the grid the color you really want as the background.
Add a gap of 1, or the desired border thickness.
.grid {
display: grid;
background-color: orange;
gap : 1;
}
.grid > * {
background-color: blue;
}
Here you can find my solution with jQuery. http://jsfiddle.net/UZJmd/7/
You just jave to put how many spans you want and then define the number of columns you want. Everything else is defined dinamically.
​1- var spanWidth = parseInt($("span").css("width"));
2- var spanSize = $("span").size();
3- var nColumns = 2;
4- var nLines = Math.floor(spanSize/nColumns+0.5);
5-
6- $(function() {
7- $("div").css({"width": (spanWidth*nColumns + 1*(nColumns-1))+"px"});
8- for(var i = 0; i <= spanSize; i++) {
10- if((i+1)%nColumns == 0) {
11- $('span').eq(i).css({"border-right": 0});
13- }
14- if(Math.floor(i/nColumns) >= nLines-1) {
15- $('span').eq(i).css({"border-bottom": 0});
16- }
17- }
18- });
In line 3 we define the number of columns we want.
In line 10 we check if it's the last span of the line and we set the right border to 0.
In line 14 we check if we are in the last line and then set the bottom border to 0.

When should I define CSS class selectors inside other class selector definitions?

EDIT 1
Based on suggestions, I tried this:
.lower-container {
justify-content: center;
position: absolute;
width: 92vw;
// height: 46vh; <--- no height defined
/* nested for adding classes to change position and height of lower-container */
.lower-container.lower-full {
height: 92vh;
top: 0;
}
.lower-container.lower-mid {
height: 46vh;
top: 46vh;
}
.lower-container.lower-closed {
height: 1vh;
top: 91vh;
}
}
In the Elements Panel I see:
But in the Styles panel I have:
So although I'm applying the additional class, the height is not getting set, and the additional class isn't showing in the styles.
Original question
I'm defining some classes inside of others like this:
.lower-container {
height: 46vh;
display: flex;
justify-content: center;
...
.lower-full {
height: 92vh;
}
}
Then when it comes time to change the height I'm doing:
lowerContainerElement.classList.add('lower-full')
But on the console, the element doesn't have the .lower-full style in the Styles panel,
even though in the Elements panel it shows class="{other classes} lower-full"
What am I doing wrong?
You cannot define a CSS selector inside another one with just vanilla CSS, you would need a pre-processor like SASS.
With CSS you can specify properties for when an element has only .lower-container or when it has both. That will be the equivalent of what you were trying to accomplish in your original code.
.lower-container {
height: 46vh;
display: flex;
justify-content: center;
...
}
.lower-container.lower-full {
height: 92vh;
}
If you are using SCSS files already then you are using the incorrect syntax
.lower-container {
height: 46vh;
display: flex;
justify-content: center;
...
&.lower-full {
height: 92vh;
}
}
Edit based on newest edit: Code should look like this:
.lower-container {
justify-content: center;
position: absolute;
width: 92vw;
// height: 46vh; <--- no height defined
/* nested for adding classes to change position and height of lower-container */
&.lower-full {
height: 92vh;
top: 0;
}
&.lower-mid {
height: 46vh;
top: 46vh;
}
&.lower-closed {
height: 1vh;
top: 91vh;
}
}

CSS Variables (custom properties) in Pseudo-element "content" Property

Example use (what I want)
div::after {
content: var(--mouse-x) ' / ' var(--mouse-y);
}
Test case showing it NOT working:
CodePen: CSS Variables in Pseudo Element's "content:" Property (a test case) by Jase Smith
document.addEventListener('mousemove', (e) => {
document.documentElement.style.setProperty('--mouse-x', e.clientX)
document.documentElement.style.setProperty('--mouse-y', e.clientY)
// output for explanation text
document.querySelector('.x').innerHTML = e.clientX
document.querySelector('.y').innerHTML = e.clientY
})
/* what I want!! */
div::after {
content: var(--mouse-x, 245)" / " var(--mouse-y, 327);
}
/* setup and presentation styles */
div::before {
content: 'mouse position:';
}
div {
position: absolute;
top: 0;
left: 0;
transform: translate(calc(var(--mouse-x, 245) * 1px), calc(var(--mouse-y, 327) * 1px));
width: 10em;
height: 10em;
background: #ff3b80;
color: #fff;
display: flex;
flex-flow: column;
align-items: center;
justify-content: center;
border-radius: 100%;
will-change: transform;
}
body {
margin: 2em;
font-family: sans-serif;
}
p {
max-width: 50%;
min-width: 25em;
}
<!-- test case: element with pseudo element -->
<div></div>
<!-- explanation (not test case) -->
<main>
<pre><code>div::after {
content: var(--mouse-x) ' / ' var(--mouse-y);
}</code></pre>
<h1>If this worked...</h1>
<p>
We should see something like this: <b><span class="x">245</span> / <span class="y">327</span></b> updating with the mousemove coordinates inside the pseudo <i>::after</i> element for the div.
</p>
</main>
Edit for clarity: CSS custom properties with integer values can be displayed in a pseudo-element's content property via a CSS counter.
div {
--variable: 123;
}
span:after {
counter-reset: variable var(--variable);
content: counter(variable);
}
<div>The variable is <span></span>.</div>
.coordinates:before {
counter-reset: x var(--x) y var(--y);
content: 'The coordinates are (' counter(x) ', ' counter(y) ').';
}
<div class="coordinates" style="--x: 1; --y: 2"></div>
Original Answer
Got it to work using a hack involving CSS Counters. Enjoy.
div::after {
counter-reset: mouse-x var(--mouse-x, 245) mouse-y var(--mouse-y, 245);
content: counter(mouse-x) " / " counter(mouse-y);
}
Full code in action:
document.addEventListener('mousemove', (e) => {
document.documentElement.style.setProperty('--mouse-x', e.clientX)
document.documentElement.style.setProperty('--mouse-y', e.clientY)
// output for explanation text
document.querySelector('.x').innerHTML = e.clientX
document.querySelector('.y').innerHTML = e.clientY
})
/* what I want!! */
div::after {
counter-reset: mouse-x var(--mouse-x, 245) mouse-y var(--mouse-y, 245);
content: counter(mouse-x) " / " counter(mouse-y);
}
/* setup and presentation styles */
div::before {
content: 'mouse position:';
}
div {
position: absolute;
top: 0;
left: 0;
transform: translate(calc(var(--mouse-x, 245) * 1px), calc(var(--mouse-y, 327) * 1px));
width: 10em;
height: 10em;
background: #ff3b80;
color: #fff;
display: flex;
flex-flow: column;
align-items: center;
justify-content: center;
border-radius: 100%;
will-change: transform;
}
body {
margin: 2em;
font-family: sans-serif;
}
p {
max-width: 50%;
min-width: 25em;
}
<!-- test case: element with pseudo element -->
<div></div>
<!-- explanation (not test case) -->
<main>
<pre><code>div::after {
content: var(--mouse-x) ' / ' var(--mouse-y);
}</code></pre>
<h1>If this worked...</h1>
<p>
We should see something like this: <b><span class="x">245</span> / <span class="y">327</span></b> updating with the mousemove coordinates inside the pseudo <i>::after</i> element for the div.
</p>
</main>
I'm not quite sure if I understood your question correctly, but I think here's a solution...
You can define a custom attribute to your <div> element.
<div data-position></div>
Then assign the position in this attribute with javascript:
var position = e.clientX + " " + e.clientY
document.querySelector("div").setAttribute('data-position', position)
Finally use the attr() CSS function in the content property of your pseudoelement.
div::after {
content: attr(data-position);
}
And voila.
Code Snippet:
document.addEventListener('mousemove', (e) => {
document.documentElement.style.setProperty('--mouse-x', e.clientX)
document.documentElement.style.setProperty('--mouse-y', e.clientY)
var position = e.clientX + "/" + e.clientY
document.querySelector("div").setAttribute('data-position', position)
// output for explanation text
document.querySelector('.x').innerHTML = e.clientX
document.querySelector('.y').innerHTML = e.clientY
})
/* what I want!! */
div::after {
content: attr(data-position);
}
/* setup and presentation styles */
div::before {
content: 'mouse position:';
}
div {
position: absolute;
top: 0;
left: 0;
transform: translate(calc(var(--mouse-x, 245) * 1px), calc(var(--mouse-y, 327) * 1px));
width: 10em;
height: 10em;
background: #ff3b80;
color: #fff;
display: flex;
flex-flow: column;
align-items: center;
justify-content: center;
border-radius: 100%;
will-change: transform;
}
body {
margin: 2em;
font-family: sans-serif;
}
p {
max-width: 50%;
min-width: 25em;
}
<div data-position></div>
<span class="x"></span>/<span class="y"></span>
content property only allows Strings, and since you are dealign with numbers and CSS cannot cast variables, you are left with the option to create another set of variables (from JS) which will serve as the printed values, and will be of type String.
To set --mouse-x-text as String, it's not enough to cast it to that type using the old casting trick 2+"" = "2", but JSON.stringify is the only way what I know that can output a "real" string, out of the already-string value, which kind-of mean a string of a string, since CSS seems to strip the first string-layer.
document.addEventListener('mousemove', ({clientX:x, clientY:y}) => {
const {style} = document.documentElement
style.setProperty('--mouse-x', x)
style.setProperty('--mouse-y', y)
// for printing
style.setProperty('--mouse-x-text', JSON.stringify(x+""))
style.setProperty('--mouse-y-text', JSON.stringify(y+""))
})
body::before{
content: "X:"var(--mouse-x-text)" Y:"var(--mouse-y-text);
}
You need quotation marks around the values of your custom properties.
document.documentElement.style.setProperty('--mouse-x', "'" + e.clientX + "'")
document.documentElement.style.setProperty('--mouse-y', "'" + e.clientY + "'")

CSS: self-adjusting table with max width that clips to content width

I am struggling to make the adjustable parent div fit the content:
(I want the widening white space on the right to go away)
http://jsfiddle.net/TDq7T/42/
max-width: and width:fit-content or auto, don't work together
#parent {
display: block;
max-width:40%;
overflow:hidden;
background: rgba(255,255,255,1.0);
}
#child {
display: block;
width:50px;
height:50px;
background: rgba(0,0,0,1.0);
float:left;
margin: 10px;
}
I tried changing the display modes, clip: auto, width:auto adding another subparent but to no avail :(
since you used javascript to generate html elements I believe it won't be a problem to style them with javascript (jquery) as well:
http://jsfiddle.net/TDq7T/75/
function calculate_m_width() {
var d_width= $(document).width();
var m_width= Math.floor((d_width*.4)/70)*70;
$("#menu").css("width",m_width);
}
calculate_m_width();
window.onresize = function() {
calculate_m_width();
}
each time the browser is resized the width of the menu will be recalculated as number of elemnets x their width (50+2x10)
Use display: flex; on #menu (and erase float: center):
http://jsfiddle.net/d3rp294u/
I'm not sure that is what you want, but I will give a try.
var menu = document.createElement('div');
menu.id = 'menu';
document.body.appendChild(menu);
var d = document.createElement('div');
d.id = 'child';
document.body.appendChild(d);
var e = document.createElement('div');
e.id = 'child';
document.body.appendChild(e);
var f = document.createElement('div');
f.id = 'child';
document.body.appendChild(f);
var g = document.createElement('div');
g.id = 'child';
document.body.appendChild(g);
var h = document.createElement('div');
h.id = 'child';
document.body.appendChild(h);
menu.appendChild(d);
menu.appendChild(e);
menu.appendChild(f);
menu.appendChild(g);
menu.appendChild(h);
#menu {
padding: 0;
margin: 0;
max-width: 280px;
overflow: hidden;
background: #ccc;
display: flex;
float: center;
-webkit-flex-flow: row wrap;
-moz-justify-content: flex-start;
-webkit-justify-content: flex-start;
justify-content: flex-start;
}
#child {
background: rgba(0, 0, 0, 1.0);
width: 50px;
height: 50px;
margin: 10px;
align-self: flex-start;
display:
}

Tizen SDK CSS ID Not Being Rendered

I am using the Tizen 2.3.1 SDK for wearables and have run into an issue where no matter what I do to the style.css file, adding any new ids simply refuses to work.
* {
margin: 0;
padding: 0
}
html, body {
width: 100%;
height: 100%;
background-color: black;
}
#str_day {
position: absolute;
display: -webkit-flex;
width: 50%;
height: 50%;
background: yellow;
color: yellow;
z-index: 4;
opacity: 1;
}
h1 {
font-size: 1.4em;
margin: 10px 0 20px 10px;
color: #6587ac;
}
#box {
display: -webkit-flex;
-webkit-align-items: center;
width: 100%;
height: 100%
}
.canvas {
background: #000;
width: 320px;
height: 320px;
margin: auto;
}
This is my code. I am trying to add the str_day id however it doesn't show up when I run the package through the emulator. The rest of the css (the canvas element, mainly) works fine, but str_day just doesn't show up. I tried specifying the z-index and opacity in case some weird issue was occuring but that doesn't seem to be the problem.
This is my full code on github.
https://github.com/JoyfulOwl/RadialWatch/commit/86d096710c7187b6b3679e02416548e18a3e986e
Probably because of improper CSS layout str_day is rendered/painted outside the viewport of your watchface because of which its not visible.
I think better would be to use canvas fillText command to print the date on canvas.
Try below example.
var canvas = document.getElementById("myCanvas");
var context=canvas.getContext("2d");
context.font="30px Comic Sans MS";
context.fillStyle = "red";
context.textAlign = "center";
context.fillText(str_Day, mCenterX, mCenterY); // mCenterX & mCenterY are the position where text has to be shown.

Resources