Good day, dear readers and writers!
Today I will tell you how the project faced me with the task of manufacturing an adaptive slider and what came of it
I am writing this article not so much because I want to get a community response to solving this problem, but also because solving the questions of the article seems fundamental to me to understand the adaptability of the slider on the web. If someone has already written such components, please respond and share similar experiences
In the React application, you need to make a carousel (hereinafter I will use this name), the elements of which harmoniously look on the screen of any size. There are several limitations:
Many carousels (React Owl Carousel is not an exception) use the special active class to show which describes the elements that are currently displayed on the screen.
To display an infinite loop on the screen, the first and last elements are duplicated (the mechanics and problems of this dubbing are a topic for a separate article).
Properties are described by special objects, we will be interested in the responsive object, which is responsible for the reassignment of properties.
The rest of the data on the mechanics of work will be clear as the solution is described.
At first everything went smoothly - the elements themselves were written and stylized, the basic properties of the entire carousel were spelled out. Problems started when setting property {loop: true}
When scrolling to the end of the list, free space remained in the carousel and for some time it was it that was scrolling.
The reason was the maximum width of the element, not consistent with their number. A concrete example is the width of the container 1190 px, with the number of elements set to 3.
In other words, the carousel expects 3 elements to stretch to 1190px, and they cannot become larger than 150px.
The problem takes on a different angle: if there are too many elements per container, their width becomes too small (and there is content inside them!) If I set the min-width property, then on some screen sizes the elements crawl onto each other, ignoring the margin, which violates the conditions .
If you approach the problem sequentially, it is obvious that you have to give up something, in my case it was the minimum width of the element.
What should be the minimum width of the element so that for all container screens the adaptability conditions are met?
// const getBackTrace = (minScreen = 300, maxElementWidth = 150) => { let backTrace = {} for (let minElementWidth = maxElementWidth; minElementWidth > 0; minElementWidth--){ // // backTrace for(let screen = minScreen; screen <= 1100; screen++){ let elementCount = screen / minElementWidth | 0 if((screen / elementCount) > maxElementWidth){ backTrace[minElementWidth] = screen break } } } for(let key in backTrace){ // , if (backTrace[key - 1] == undefined){ backTrace.result = key - 1 return backTrace } } } // getBackTrace(300, 150).result = 100
The result in 100px did not suit me, since it does not allow me to fit all the content in the element. Therefore, we continue the search until we find the right value and look for what else you can sacrifice.
Remember the subtitle? To search, write a function
const getMinScreen = (minWidth = 300, maxWidth = 767, maxElementWidth = 150) => { let research = [] // , // getBackTrace, for(let min = minWidth; min < maxWidth; min++){ let { result } = getBackTrace(min, maxElementWidth) research.push({result, min}) } // " " return research .reduce((acc, curr, idx, arr) => { let obj = {} let {min, result} = curr obj[min] = result if(idx == 0) return obj if(arr[idx-1].result == result){ return {...acc} } else { return {...acc, ...obj} } }, {}) } /* Returned object {300: 100, 303: 101, 306: 102, 309: 103, 312: 104, 315: 105, 318: 106, 321: 107, 324: 108, 327: 109, 330: 110, 333: 111, 336: 112, 452: 113, 456: 114, 460: 115, 464: 116, 468: 117, 472: 118, 476: 119, 480: 120} 480 */
Considering the obtained object, a big leap is seen when moving from 336px to 452px.
I made a strong-willed decision to limit adaptability to 36px.
It would seem that the problem has been solved, but such a solution only proves that compliance with the conditions is possible for screens from 336px, but does not describe the method. But there are different conditions that limit me in the production of an object with adaptability properties
Having accepted for myself that the minimum width of an element without losses can be 107 px, varying the margin value, I came to the following indicators:
Screen | margin | minimum width |
---|---|---|
336+ | five | 107 |
468+ | ten | 107 |
763+ | 15 | 112 |
The only thing left is to collect the received data in a heap and implement the adaptive object:
getResponsiveOwlItems = () => { let responsive = {}; responsive[0] = {items: 2, nav: false} // 112 = 107 (minimal div) + 5 (margins) let itemMinWidthReference = 112; const getOneWidth = deviceWidth => deviceWidth / itemMinWidthReference | 0 // 1190 - container width for(let i = itemMinWidthReference * 3 + 20; i <= 1190; i += itemMinWidthReference){ // .container padding > 768 90px + padding 90(.container) // .container padding < 768 40px + padding -40(.container) // +20px stagePadding let padding = i > 767 ? 200 : 20 if(i > (468 + padding)) { itemMinWidthReference = 117 } if(i > (767 + padding)) { itemMinWidthReference = 127 } let items = getOneWidth(i - padding) let nav = i > 700 ? true : false let margin = 5; if (i > 468){ margin = 10 } if (i > 767){ margin = 15 } responsive[i.toString()] = {items, nav, margin} // itemMinWidthReference i = i - (i % itemMinWidthReference) + 1 } return responsive; }
On the day of publication, everything looks logical, and I could not reproduce the error in the carousel - everything probably works as intended.
Thank you for your attention, waiting for your comments and comments!
Source: https://habr.com/ru/post/461525/
All Articles